【问题标题】:Best way of updating UI in event handler after fire event in other thread [closed]在其他线程中触发事件后在事件处理程序中更新 UI 的最佳方法 [关闭]
【发布时间】:2020-06-01 03:57:37
【问题描述】:

我的项目需要通过事件更新一些 UI 元素,并且一些事件在异步或后台线程中触发。所以我需要在事件处理程序中添加一些线程安全的代码。

但我发现项目中有很多相同的情况。这些零散的线程安全代码让整个项目代码相当难看,希望有办法改进。

这里是其他线程中的火灾事件示例代码:

public static class MyAsyncClass
{
    public static event Action MyEvent;
    public static void AsyncCallEvent()
    {
        //...
        Task.Run(() => {
            while(runningFlag)
            {
                //...
                if(flag)
                    MyEvent?.Invoke();
            }
        });
    }
}
public class MyWindow : Window
{
    //...
    private void OtherMethod()
    {
        UpdateText();
    }
    private void Init()
    {
        MyAsyncClass.MyEvent += UpdateText;
    }
    private void UpdateText()
    {
        //Do update
    }
    //...
}

这里有两种updateText的代码:

//Clear, but not cross-thread safety
//will fail in cross-thread event invoking
private void UpdateText()
{
    MyTextBox.Text = "NewText";
}
//Cross-thread safe, but make code noisy
private void UpdateText()
{
    Dispatcher.Invoke(() => MyTextBox.Text = "NewText");
}

当然,第二个代码肯定更好,但是如果将它添加到所有可能被异步调用的事件处理程序中,代码会变得令人不快。

有更清洁的解决方案吗?

【问题讨论】:

  • 如果您的代码有效,我想这与 SO 无关,您应该在 anotherstackexchange 网站上提出这个问题?
  • @vasily.sib 这个问题可能符合codereview.stackexchange.com/help/dont-ask的描述所以我不会在CodeReview问它
  • 这里没有异步。您刚刚启动了一个后台线程。只是不要在后台线程上引发 UI 相关事件。
  • 是否可以修改MyAsyncClass,例如通过添加SynchronizingObject 属性?

标签: c# wpf multithreading cross-thread


【解决方案1】:

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

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

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

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

【讨论】:

  • 我猜 OP 正在使用 Task.Run 调用事件,以避免被事件的顽皮处理程序阻塞。这与使用 MyEvent?.BeginInvoke(... 异步调用它并没有太大区别。
  • 其实这是一个轮询任务,我已经修改了我的代码。这个解决方案看起来不错,但我决定在重新打开问题后等待一些新的答案。
猜你喜欢
  • 2015-10-01
  • 2011-01-25
  • 1970-01-01
  • 2010-09-17
  • 1970-01-01
  • 2013-11-23
  • 2013-10-23
相关资源
最近更新 更多