wpf 我应该如何简化Dispatcher在UI线程上更新控件的代码[已关闭]

nxowjjhe  于 2022-12-14  发布在  其他
关注(0)|答案(1)|浏览(137)

已关闭。此问题为opinion-based。当前不接受答案。
**想要改进此问题吗?**请更新问题,以便editing this post可以使用事实与引用来回答.

两年前就关门了。
此帖子已在20小时前编辑并提交审阅,无法重新打开帖子:
原始关闭原因未解决
Improve this question
我的代码需要通过triggerd事件来更新一些UI元素,而一些事件是在异步或后台线程中触发的,而不是在STA线程中触发的。所以我需要在事件处理程序中使用Dispatcher.Invoke
但是有很多相同的情况需要应用,这些分散的线程安全代码使得项目代码看起来一点也不优雅,希望有一种方法可以改进它。
下面是其他线程中fire事件的示例代码(不是真实的的代码):

//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(){}...
    //...
}

当然,使用Dispatcher.Invoke肯定更好,但是如果把它添加到所有可能潜在地被异步调用的事件处理程序中,代码就会变得让人不愉快。
有没有更干净的解决方案?

fwzugrvs

fwzugrvs1#

您可以在调度程序线程上调用UpdateText()本身:

private void Init()
{
    MyAsyncClass.MyEvent += () => Dispatcher.Invoke(UpdateText);
}

private void UpdateText()
{
    MyTextBox.Text = "NewText";
}

但是,代码真正丑陋的地方在于,您使用Task.RunMyAsyncClass中的另一个线程上显式执行事件处理程序。您应该在引发事件的同一个线程上调用事件处理程序。然后,由事件的订阅者选择是否将事件处理程序中的代码卸载到另一个线程。

相关问题