Confusion about what the WPF Dispatcher object is - wpf

Could someone tell me in simple layman terms, what a WPF Dispatcher object is?
Also, I sometimes see this line of code in the constructor of an object. What does Dispatcher.CurrentDispatcher represent?
Dispatcher dispatcher = Dispatcher.CurrentDispatcher;
I know this has got something to do with making sure you don't access objects from a thread different from the thread that owns the object, but I'm having trouble wrapping my head around exactly what a Dispatcher is/does.

I think the MSDN page should give a good description, in short:
The Dispatcher maintains a prioritized queue of work items for a specific thread.
And the CurrentDispatcher:
If a Dispatcher is not associated with the current thread, a new Dispatcher will be created. This is not the case with the FromThread method. FromThread will return null if there is not a dispatcher associated with the specified thread.

http://weblogs.asp.net/pawanmishra/archive/2010/06/06/understanding-dispatcher-in-wpf.aspx
The main UI thread is the only thread that can access the user interface.
The dispatcher is a means of passing messages to the main UI thread.

Related

How to deal with cross-thread access exceptions?

A common exception one can get when working with multiple threads in WPF is:
The calling thread cannot access this object because a different thread owns it
What are the options to deal with this properly?
Depending on the situation there are various options:
Accessing a control from another thread
e.g. updating a TextBlock with progress information.
Data Binding:
In this case the easiest thing you can do is avoiding the direct interaction with the control. You can just bind the property you want to access or modify to an object whose class implements INotifyPropertyChanged and then set the property on that object instead. The framework will handle the rest for you. (In general you rarely should need to interact with UI-elements directly, you can almost always bind the respective properties and work with the binding source instead; one case where direct control access may be necessary is control authoring.)
There are some cases where data binding alone is not enough, for example when trying to modify a bound ObservableCollection<T>, for this you need...
Dispatching:
You can dispatch your accessing code to the thread owning the object, this can be done by calling Invoke or BeginInvoke on the Dispatcher owning the object being accessed (getting this Dispatcher is possible on another thread).
e.g.
new Thread(ThisThreadStart).Start();
void ThisThreadStart()
{
textBlock.Dispatcher.Invoke(new Action(() => textBlock.Text = "Test"));
}
If it is not clear on which thread a method is executed you can use Dispatcher.CheckAccess to either dispatch or execute an action directly.
e.g.
void Update()
{
Action action = () => myTextBlock.Text = "Test";
var dispatcher = myTextBlock.Dispatcher;
if (dispatcher.CheckAccess())
action();
else
dispatcher.Invoke(action);
}
If an object is not a DispatcherObject and you still need the associated Dispatcher you can use Dispatcher.CurrentDispatcher in the thread creating the object (so doing this in the method being executed by a thread will not do you any good). For convenience as you usually create objects on the application's main UI thread; you can get that thread's Dispatcher from anywhere using Application.Current.Dispatcher.
Special cases:
BackgroundWorker
Move any control access to ProgressChanged as it occurs on the thread that created the instance (which should of course be the UI-thread)
Timers
In WPF you can use the DispatcherTimer for convenience, it does the dispatching for you so any code in Tick is invoked on the associated dispatcher. If you can delegate the dispatching to the data binding system you of course can use a normal timer as well.
You can read more about how the Dispatcher queue works and WPF threading in general on MSDN.
Accessing an object created on another thread
e.g. loading an image in the background.
If the object in question is not Freezable you should in general simply avoid creating it on another thread or restricting access to the creating thread. If it is Freezable you just need to call Freeze to make it accessible to other threads.
Accessing a data object from another thread
That is, the type whose instance is being updated is user-code. If an exception is thrown this situation probably came about by someone using DependencyObject as base type for a data class.
This situation is the same as accessing a control and the same approaches can be applied but usually it should be avoided in the first place. Granted, this allows for simple property change notifications via dependency properties and those properties can also be bound but often enough this is just not worth giving up thread-independency. You can get change notifications from INotifyPropertyChanged and the binding system in WPF is inherently asymmetrical, there always is a property that is bound (target) and something that is the source for this binding. Usually the UI is the target and the data is the source, meaning that only UI components should need dependency properties.
That would be several hundred lines of code, for something I "figured out".
But the summary is:
App_OnStartup
generate a background thread
in the callback,
Call
Application.Current.MainWindow.Dispatcher.CheckAccess() - gets the exception
Application.Current.Dispatcher.CheckAccess() does not
I have a udp listener object that communicates through events where the method/callbacks are +='ed in my mainWindow wpf .cs file.
The event handler functions are called with parameters, one being the message I want displayed in a listbox in the mainWindow.cs
Using the information in this thread by H.B. above;
I have added, tested and handled the crossthread in wpf in my eventhandler callback using the following code, but I use a real message not a hard coded one:
listBox1.Dispatcher.Invoke(new Action(() => listBox1.Items.Add("MessageHere")));
UPDATE:
This is better because you can put more things in the anonymous function.
listBox1.Dispatcher.Invoke((Action)delegate
{
listBox1.Items.Add(e.ReaderMessage);
});

Application Dispatcher and Control Dispatcher

Assume i have control button with name "button1" and function with name "doSomething". Function "doSomething" is called from another thread.
i have two method to call function doSomething from UI thread.
First, from control button dispatcher
this.button1.Dispatcher.BeginInvoke(new Action(() => { doSomething(); }));
and Second, from application dispatcher
this.Dispatcher.BeginInvoke(new Action(() => { doSomething(); }));
The result is same, what is the real different ?
The same dispatcher instance is referenced in all controls owned by the same thread. There is no difference.
All of UI controls (which were created normally), share the same dispatcher instance. That dispatcher is working on UI thread. If you create some control on backgroud thread, it will create new dispatcher on that thread, and this will not be very good.
The best way to avoid most problems with threading and UI controls both in WinForms and WPF is to use System.Threading.SynchronizationContext.Current. The workflow is simple: you get System.Threading.SynchronizationContext.Current while you are on UI thread and save it somewhere (for example in a public static field). Then, whenever you want to run some code on UI thread, you access that persisted SynchronizationContext intance and use its Send or Post methods. It will run you delegates on thread, where SynchronizationContext was achieved (for current case on UI thread). Also it is smart enough, to use the current way of Invoking (message loop for WinForms and dispatcher for WPF) and also if you are already calling from UI thread it will just run your delegate synchronously.
Just keep in mind, that you should get SynchronizationContext only after you create your first control on the current UI thread, because SynchronizationContext will be initialized right after that.
In most of the case, We have single UI thread. So, It doesn't make difference you call
control.Dispatcher(which comes inherited from DispatcherObject parent of the controls).
or
Disptacher.Current.
But there are scenarios, where you will end up having multiple dispatchers.
So, in that situation, Control.Dispatcher will help as It will find out the current dispatcher to respect Thread Affinity. In this Dispatcher.Current won't help.
One scenario, having dedicated thread(with dispatcher) for displaying busy indicator as default UI thread is busy in rendering large list of controls.
However, with SynchronizationContext is another way to avoid such issues. but what if that context or thread is no longer required or it has been set to null by any other developer. So, It is always wise to go for Control.Dispatcher in my opinion.

odata on silverlight runs on UI thread only

We're working with OData on Silverlight, using DataServiceCollection to get the data.
All calls for fetching data (LoadAsync() LoadNextPartialSetAsync()) are done on a worker thread. However, the 'LoadCompleted' callback as well as deserialization and object materialization are done the UI thread.
We decompiled the System.Data.Services.Client.DLL where the DataServiceCollection is, and saw that indeed all code handling the response of the OData is dispatched to the UI thread.
Is there any way to get the deserialization to be called on a worker thread instead?
thanks
Yaron
Well...
It seems the OData collections deliberately moves processing the UI thread. I'm guessing this is done because old objects might have properties the UI is bound to. These properties might change when loading additional data.
Using the query itself, I was able to get the response on a worker thread. However, doing this means one MUST detach the objects from the OData context (or clone them) if UI is bound to any property. Otherwise consequent queries might cause property changed events when objects are materializing on the worker thread.
The problem you have is that the DataServiceCollection<T> is derived from the ObservableCollection<T>. Which in turn is designed to be bound to UI elements. When changes are made to the membership of a ObservableCollection<T> a binding expression observing it is notified. This binding expression then attempt to update the target UI element. If the notification arrives on a non-UI Thread then an exception occurs.
Hence the DataServiceCollection<T> deliberately shifts materialisation to the UI Thread so that as items appear in the collection the resulting change notifications do not result in an exception. If this behaviour is unacceptable to you then DataServiceCollection<T> is not for you.
Instead execute the query yourself via the DataServiceQuery<T>.BeginExecute. The callback you pass to BeginExecute will execute on a worker thread (at least it will when ClientHTTP is being used, I have yet established what will happen when XmlHttp is being used). Here you can enumerate the results and place them in whatever collection type your prefer. You can the switch to the UI thread when you are ready to display the results.
The callback will be called always on a UI thread.
If the request was using the XmlHttp stack (which is the default if you call it from a UI thread) then the networking stack invokes the callback registered by the WCF Data Service on the UI thread. So in this case it's a behavior of the DataServiceCollection/DataServiceContext but a behavior of the underlying network stack.
If you call the request from a non-UI thread or you explicitely set the Http stack to be Client then the callback will come back on a non-UI thread (potentially a different one). We still move it back to the UI thread before letting the caller know. The reason for this is consistency, especially since you can't interact with UI elements on background threads.
If you would execute the query manually, so for example through DataServiceContext.BeginExecute, then the materialization (or most of it anyway) is driven by the caller, since the call returns just IEnumerable which is not yet populated. If you would then transfer execution to a worker thread and enumerate the results there, the materialization will happen on that thread.
Just curious, why do you want to move it? Are you processing so much data, that it causes a visible UI lag?

WPF Databinding thread safety?

Well lets say i have an object that i databind to, it implements INotifyPropertyChanged to tell the GUI when a value has changed...
if i trigger this from a different thread than the GUI thread how would wpf behave?
and will it make sure that it gets the value of the property from memory and not the cpu cache?
more or less im asking if wpf does lock() on the object containing the property...
Value changes fired by INotifyPropertyChanged are automatically marshalled back onto the dispatcher. (http://blog.lab49.com/archives/1166)
Fire this event on any thread you like...
Value changes fired by INotifyCollectionChanged are NOT reliably marshalled onto the dispatcher. (http://csharplive.wordpress.com/2008/09/11/wpf-data-binding-observablecollection-cross-thread-binding-support/)
If you need to update an observable collection from a different thread, follow the advice in this link
In addition to #Rob Fonseca-Ensor's answer, there is some good news for those lucky enough to use WPF4.5:
WPF enables you to access and modify data collections on threads other than the one that created the collection. This enables you to use a background thread to receive data from an external source, such as a database, and display the data on the UI thread. By using another thread to modify the collection, your user interface remains responsive to user interaction. (https://msdn.microsoft.com/en-us/library/bb613588(v=vs.110).aspx#xthread_access)
There's a helpful summary by Jonathan Antoine: http://www.jonathanantoine.com/2011/09/24/wpf-4-5-part-7-accessing-collections-on-non-ui-threads/
In practice it seems to work as expected and seems to be thread-safe (haven't seen anything odd happen or exceptions as a result of updating on background thread). I believe it invokes on to the UI thread when needed, but I'm not too familiar with the internals.

WPF: Is there a simple way to create a Progress Window?

I tried creating one, but the BackgroundWorker in Window1 couldn't access the ProgressBar in Window2 once the reportProgress was activated, because "The calling thread cannot access this object because a different thread owns it".
Seems there's a lower level thread model I could use, but it also seems a lot more complicated.
You just need to get the ProgressBar disptacher.
You can access the ProgressBar with:
Window2.prograssbar.Dispatcher.Invoke(
() => /*the code for modifying the progressbar*/ );
In WPF, UI controls and properties may only be activated from the UI thread. In order to change the progress bar's value from a different thread, you can add a command to the GUI thread's dispatcher queue. You can do this by passing a delegate to the Dispatcher.Invoke() method. See the article at http://msdn.microsoft.com/en-us/magazine/cc163328.aspx for more details.
You need to look into Delegates

Resources