3

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?

Vaccano
  • 78,325
  • 149
  • 468
  • 850
  • There is a way to determine if a Dispatcher.Invoke is required. Would that answer your question? – BradleyDotNET Mar 05 '14 at 23:45
  • @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 Mar 05 '14 at 23:49
  • 1
    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 Mar 05 '14 at 23:50
  • 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 Mar 05 '14 at 23:52
  • 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 Mar 06 '14 at 00:01

3 Answers3

4

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 :

Community
  • 1
  • 1
har07
  • 88,338
  • 12
  • 84
  • 137
0

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.

Hakan Fıstık
  • 16,800
  • 14
  • 110
  • 131
Wonderbird
  • 392
  • 4
  • 12
0

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

Hakan Fıstık
  • 16,800
  • 14
  • 110
  • 131