Reputation: 450
I have setup a WCF host that operates on an instance of an object. When the following method is called from a WCF client, the error, "The calling thread cannot access this object because a different thread owns it", is thrown.
public List<PrintQueueData> getPrintQueues()
{
List<PrintQueueData> resultQueues = new List<PrintQueueData>();
List<PrintQueue> queues = queueCollection;
foreach (PrintQueue q in queues)
{
// This throws an exception
resultQueues.Add(new PrintQueueData(q.HostingPrintServer.ToString(), q.Name));
// This does NOT throw any exceptions
resultQueues.Add(new PrintQueueData("1", "2");
}
return resultQueues;
}
What should I do to correct this error?
EDIT: queueCollection is a field of the class containing this method.
EDIT: queueCollection is declared at the beginning of this class and it's type is a list of printqueue, the same as what it is being assigned to in this method.
EDIT: I had a timer running that used queueCollection, however, I set Timer.Enabled to false and the error still occurred.
Upvotes: 2
Views: 1825
Reputation: 517
I know this is quite an old question but I've recently ran into a very similar problem and figured out the root cause.
I don't know how is obtained queueCollection in the original code of the question, but I assume it was using an instance of PrintServer, calling its method GetPrinterQueues(). In my case, I was creating the instance of PrintServer and saving the resulting PrintQueueCollection in a field of my own class, and using this collection later, once the instance of PrintServer was out of scope, so probably being disposed by Garbage collector.
I was stubbornly thinking that the cause was something to do with using Dispatcher.Invoke and other solutions around the posible conflicts between the UI thread and other threads but once I changed my code to only use PrintQueueCollection while its PrintServer parent still being in the same scope, the code ran without this exception.
Upvotes: 0
Reputation: 31
The "PrintQueue" type behaves like a "DependencyObject". It is bound to the "Dispatcher" of the current thread similar to UI elements in WPF. That's way you cannot use it on thread different from the thread that created the queue. You must either cache your "PrintQueueData" objects (instead of your "PrintQueue" objects) or instantiate the "PrintQueue"s on each method call.
The actual exception you get comes from "System.Windows.Threading.Dispatcher.VerifyAccess()" which is called by "System.Printing.PrintQueue.VerifyAccess()". The latter is called whenever you access a property or a method of the print queue.
Upvotes: 3
Reputation: 6891
you could try List<PrintQueue> queues = queueCollection.ToList();
or something along that line. The thing you want to achieve is create a copy of queueCollection
quickly. This should reduce the chance of the queue being 'locked' by some other thread and thus causing the said error.
alternatively, you could try to use synchronization when accessing queueCollection
. eg:
lock (wantMyQueue)
{
// Access queueCollection in here
}
where wantMyQueue
is a simply object
global variable.
Upvotes: 0