I am using .NET 3.5 .
I am making a WPF application for a project and I was just looking a bit of insight regarding the Dispatcher and multithreading. An example of my program:
Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new Action(
() =>_aCollection.Add(new Model(aList[i], aSize[i]))));
Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new Action(
() => _Data.Add(new DataPoint<double, double>(Id, aList[i]))));
Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new Action(
() => _historical[0].Add(aList[i])));
I understand that WPF does not like when another thread accessing an object other than the one that created it. However, I was thinking there has to surely be a better way than making so many dispatcher invokes, could someone please push me in the right direction at least (if there is a better solution that is).
Multiple Windows, Multiple ThreadsSome WPF applications require multiple top-level windows. It is perfectly acceptable for one Thread/Dispatcher combination to manage multiple windows, but sometimes several threads do a better job.
When we create a new thread for offloading the work and want to update the UI from the other thread then we must need Dispatcher. Only Dispatcher can update the objects in the UI from non-UI thread. Dispatcher provides two methods for registering method to execute into the message queue.
WPF applications start their lives with two threads: one for rendering and another for the UI. The rendering thread runs hidden in the background while the UI thread receives input, handles events, paints the screen, and runs application code. The UI thread queues work items inside an object called a Dispatcher.
So thread affinity means that the thread, in this case the UI thread that instantiates an object is the only thread that can access its members. So for example, dependency object in WPF has thread affinity.
You can start by being less verbose in your calls, i.e.
Application.Current.Dispatcher.Invoke(() =>_aCollection.Add(new Model(aList[i], aSize[i])));
Another trick that I like to use is to make a shortcut method like this:
public static void UiInvoke(Action a)
{
Application.Current.Dispatcher.Invoke(a);
}
Then you have even less to do, as in:
UiInvoke(() =>_aCollection.Add(new Model(aList[i], aSize[i])));
Using dispatcher.Invoke() is really just how you get the action back onto the UI thread, which is probably where these objects (_aCollection) were created in the first place. If the items in question don't have direct interaction with the UI thread, then you can create / manipulate them on a different thread, removing the need to use the dispatcher. Of course this approach could become more complicated depending on what you are doing.
The easiest way would be to combine all three calls into one:
Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new Action(
() =>
{
_aCollection.Add(new Model(aList[i], aSize[i]);
_Data.Add(new DataPoint<double, double>(Id, aList[i]);
_historical[0].Add(aList[i])
}));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With