If I'm reading your comments correctly, you are calling Dispatcher.CurrentDispatcher
from a non-UI thread. This is not how this is meant to be used.
As the documentation for Dispatcher.CurrentDispatcher says:
Gets the Dispatcher for the thread currently executing and creates a new Dispatcher if one is not already associated with the thread.
To get a valid dispatcher instance, you need to call Dispatcher.CurrentDispatcher
from the UI thread.
Also, because the documentation says that it will automatically create a dispatcher if one does not exist for the current thread, this is what explains the silent failure. You are getting a dispatcher instance, but it isn't associated to the UI thread in any way, so it isn't actually dispatching anything to the UI thread.
(Removing this, because in my tests, I get null even when I shouldn't, so it doesn't prove much it seems. The rest of the information is accurate though)
The documentation also adds:
This is not the case with the FromThread
method. FromThread
will return null
if there is not a dispatcher associated with the specified thread.
So to confirm that you are indeed getting an auto-created (invalid) dispatcher, try getting the dispatcher from Dispatcher.FromThread instead. My guess is that you will get null
.
If you want to call dispatcher.BeginInvoke
to force execution of a method on the UI thread from a worker thread, you need to call Dispatcher.CurrentDispatcher
from the UI thread and save that to a variable. You can then pass that dispatcher reference variable to the worker thread, and call BeginInvoke
on that.
// capture and save dispatcher from UI thread
Dispatcher dispatcher = Dispatcher.CurrentDispatcher;
// then you can do this from your worker thread:
dispatcher.BeginInvoke(theMethod);
Alternatively, use this.BeginInvoke
like you are doing already.
Or better yet, you can try using tasks combined with the new async-await
keywords for this sort of thing.
EDIT
For completeness, I should explain why Control.BeginInvoke
does work correctly.
As the documentation for Control.BeginInvoke says:
Executes the specified delegate asynchronously on the thread that the control's underlying handle was created on.
And later it also adds:
You can call this method from any thread.
The point is that, when you call Control.BeginInvoke
, it doesn't use the current thread to determine how to execute the delegate. It remembers which thread the control was created on (the UI thread), and makes sure to execute the delegate on that thread.
So, as long as your control is created on the UI thread (as it should), then BeginInvoke
works from any thread. This is actually quite similar to the Dispatcher
in that, as long as you obtain the Dispatcher
instance from the UI thread first, then you can call Dispatcher.BeginInvoke
from any thread as well.