My codes need to update some UI element by triggerd event, and some of event is trigged in async or background thread, not in STA thread. So I need use Dispatcher.Invoke
in event handler.
But there is so many same situation need to apply. These scattered thread-safe code makes the project codes look not elegant at all, I hope there is a way can improve it.
Here is the sample code of fire event in other thread(not real code):
//heres code just to simulate triggering events on non-STA threads
public static class MyAsyncClass
{
public static event Action MyEvent;
public static void AsyncCallEvent()
{
Task.Run(() => MyEvent?.Invoke());
}
}
public class MyWindow : Window
{
//...
private void OtherMethod()
{
//safe
UpdateText1();
//throw exception
AsyncCallEvent();
}
private void Init()
{
MyAsyncClass.MyEvent += UpdateText1;
}
private void UpdateText1()
{
//will throw exception in cross-thread invoking
MyTextBox1.Text = "NewText";
//safe but noisy
Dispatcher.Invoke(() => MyTextBox1.Text = "NewText");
}
//some else method may will be invoke by cross-thread
private void UpdateText2(){}...
private void UpdateText3(){}...
private void UpdateText4(){}...
private void UpdateText5(){}...
//...
}
Sure, use Dispatcher.Invoke
is definitely better, but if add it to all event handler that may potentially be called in async, the code will become make people unpleasant.
Is there a cleaner solution?
Well, you could invoke
UpdateText()
itself on the dispatcher thread:But what is truly ugly about your code is that you are using
Task.Run
to explicitly execute the event handler on another thread inMyAsyncClass
. You should invoke the event handler on the same thread where the event was raised. It's then up to the subscriber of the event to choose whether to offload the code in the event handler to another thread.