Reputation: 2864
Acording to my understanding Dispatcher.Invoke and Dispatcher.BeginInvoke executes on UI thread, The only difference is That Invoke is synchronous and BeginInvoke is asynchronous.My problem is when i use this code
EDisc.App.Current.Dispatcher.
Invoke(
DispatcherPriority.Normal, new Action(delegate
{
context = NavigationManager.CurrentPage.DataContext;
}));
Value of context is returned. However with the below code
EDisc.App.Current.Dispatcher.
BeginInvoke(
DispatcherPriority.Normal, new Action(delegate
{
context = NavigationManager.CurrentPage.DataContext;
}));
Context is null and i get an InvalidOperation Exception saying "
The calling thread cannot access this object because a different thread owns it.I am calling this from a WCF service which is executing with UseSynchronizationContext = false .Can anybody explain this behaviour?
Upvotes: 2
Views: 5913
Reputation: 14547
Both BeginInvoke
and Invoke
will end up calling an internal method called BeginInvokeImpl
to do the work. The difference is that Invoke
then waits for the operation to complete before returning.
And there's one other difference: if you are already on the UI thread and you're using DispatcherPriority.Send
Invoke
will actually invoke the method directly without going via BeginInvokeImpl
, meaning that the operation is processed without going via the message queue. (If you're not using Send
then any other messages already queued up with higher property than your operation will get processed first.)
But since you're presumably not on the UI thread here - you're on some WCF callback - that special case won't apply. So Invoke
ends up calling into the same underlying implementation as BeginInvoke
.
From the information you've provided, I'd have to guess that there's a missing detail somewhere here. The code you've shown should work fine, unless perhaps you have multiple UI threads in your application, and the page that happens to be in CurrentPage
belongs to different threads from time to time.
If you do have multiple UI threads, then the approach you're using - pushing everything through the current Application
object's dispatcher - isn't going to work, because you'll have multiple dispatchers. You'd need to get the right dispatcher for whichever UI element you're planning to touch.
Incidentally, one way you might accidentally end up with multiple UI threads is if you construct a UI object (e.g. a Page) on some worker thread or callback. Is it possible that you've done that somewhere?
Upvotes: 2