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?
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?
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:
UPDATE:
This is better because you can put more things in the anonymous function.
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
orBeginInvoke
on theDispatcher
owning the object being accessed (getting thisDispatcher
is possible on another thread).e.g.
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.
If an object is not a
DispatcherObject
and you still need the associatedDispatcher
you can useDispatcher.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'sDispatcher
from anywhere usingApplication.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 inTick
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 isFreezable
you just need to callFreeze
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