3
votes

I have the following code:

var queue = printer.PrintQueue;
var canPrint = ! Dispatcher.CurrentDispatcher.Invoke(()
                            => queue.IsPaperJammed || queue.IsOutOfPaper || 
                               queue.IsInError || queue.HasPaperProblem);

It is throwing the following error:

The calling thread cannot access this object because a different thread owns it

I have tried this on UI thread (using the dispatcher as shown above) and I have tried it on the current thread (without the dispatcher).

Is there a way to ask a object which thread owns it?

3
There is a way to determine if a Dispatcher.Invoke is required. Would that answer your question? - BradleyDotNET
@LordTakkera - I am not sure it would, because I try it with the Dispatcher and with out and it fails both times with the same error. My guess is that there is a different owning thread out there. - Vaccano
What is creating printer? I don't think you can easily figure out which thread owns an object, but perhaps we can figure out which one is. - vcsjones
I believe your call to the dispatcher launches a thread. (Therefore the thread trying to USE your queue is a different thread than the one that CREATED it.) I would suggest either moving the CREATING of the queue to being inside of the invoke the thread OR move the test for error conditions to BEFORE the invoke. A bigger sample of what you are trying to do may help. (The small sample gives no indication why multi-threading would even be called for in this case.) - Wonderbird
I think you are asking the wrong question. The real problem lies on why are you trying to access an object that was created from a different Dispatcher into another different Dispatcher? - 123 456 789 0

3 Answers

4
votes

Have you tried without CurrentDispatcher ? :

var canPrint = ! Application.Current.Dispatcher.Invoke(()
                            => queue.IsPaperJammed || queue.IsOutOfPaper || 
                               queue.IsInError || queue.HasPaperProblem);

CurrentDispatcher.Invoke() will invoke your code from the thread currently executing, it is non-UI thread assuming that snippet in this question is run from non-UI thread.

References :

0
votes

There is a way to determine if the CURRENT thread owns a control:
Use control.Dispatcher.CheckAccess() to check whether the current thread owns the control. If it does not own it then Invoke an Action using dispatcher.

0
votes

just crazy as it is, the following code did not work, and it still throws the exception

dlg.PrintTicket.PageMediaSize = new PageMediaSize(302.36220472, int.MaxValue);
dlg.PrintTicket.PageOrientation = PageOrientation.Portrait;

but this code worked

dlg.PrintTicket = new PrintTicket()
{
    PageMediaSize = new PageMediaSize(273, int.MaxValue),
    PageOrientation = PageOrientation.Portrait,
};

of course the both code must be in Application.Current.Dispatcher.Invoke(() => {}) but still the first will throw the exception and the second will solve the problem