In my main window (Thread A), I start a new thread (Thread B) which does some work while the user waits.
Thread B fires events if there is an error or extra information is required from the user, Thread A will listen to these events.
In Thread A's event listener I need to show dialog messages to the user, I have a custom dialog window and show it using dialogWindow.showDialog()
. This works fine, but causes an error when I try and set the owner of the dialog, I do this dialogWindow.Owner = Window.GetWindow(this)
.
The error that I get is: The calling thread cannot access this object because a different thread owns it.
What is the correct way to listen for events that are fired from a different thread?
The event listener code will run implicitly at the thread which fires the event, so the event listener is not thread-bound.
If you want to show something in the UI as a result of event handling, you should do the marshalling yourself. Something like that:
void OnEvent(object sender, EventArgs args)
{
// runs in the event sender's thread
string x = ComputeChanges(args);
Dispatcher.BeginInvoke((Action)(
() => UpdateUI(x)
));
}
void UpdateUI(string x)
{
// runs in the UI thread
control.Content = x;
// - or -
new DialogWindow() { Content = x, Owner = this }.ShowDialog();
// - or whatever
}
So: you execute your computations (if any) preferrably in the background thread, without touching the UI; after that, when you know which are the needed changes in the UI, you execute the UI-updating code in the UI thread.
The Dispatcher
is a property of a control, so if your code is a part of UI, you'll have your Dispatcher for free. Otherwise, you can take the dispatcher from any of the controls (e.g., control.Dispatcher
).
The correct way to raise an event to the UI thread from the background thread is that, the event should be raised on that Dispatcher, Key here is get the dispatcher of UIthread before hand.
UIDisaptcher.BeginInvoke((ThreadStart)(() => RaiseEventToUIThread()));
when the UI thread listens to the raised event it can set the Owner property(as the window was created by the UI thread).
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