【问题标题】:Avoid requiring Dispatcher.BeginInvoke避免要求 Dispatcher.BeginInvoke
【发布时间】:2016-03-06 18:14:45
【问题描述】:

我正在编写一个库来通过 TCP 控制应用程序。连接是异步处理的,因此我在通信类中添加了一个事件以指示已收到消息。

public event EventHandler<MessageRecievedEventArgs> MessageRecieved; 

但是当我引发事件时,主类中的事件处理程序在 TCP 线程而不是主线程上执行事件处理程序。

如何避免要求用户通过调用来更新 GUI?

    private void MessageRecieved(object sender, MessageRecievedEventArgs e)
    {
        Dispatcher.BeginInvoke((Action)(()=> { textBox1.Text = e.Message; }));
    }

【问题讨论】:

  • 简短的回答,你不能轻易做到这一点。如果您使用的是 WPF,则需要在 UI 线程上运行任务,因此需要调度程序。有关您的程序结构的一些详细信息会很有用,对您正在尝试做的事情进行更详细的解释也会很有用。
  • 您肯定希望 UI 更新发生在 UI 线程上,并且您不希望库知道您的 UI 线程。你可以做的是找到一种优雅的方式来连接它们。你现在的工作方式让你担心什么?
  • @Ycoub Massad 要求用户投入使用 Dispatcher 的开销对我来说似乎很麻烦。
  • 如果你仔细想想,你需要使用调度程序的事实与它自己的客户端(UI应用程序)有关。正是 UI 应用程序具有这种特殊要求。这不是图书馆的错。其他客户,例如控制台应用程序,没有这种特殊要求。
  • 这是一个好点...

标签: c# multithreading asynchronous


【解决方案1】:

使用上面 Hans Passant 的评论,我只是将我的代码修改如下:

    private SynchronizationContext MainUIThread; //as a class field

在构造函数中:

public MyClass()
{
      MainUIThread = SynchronizationContext.Current;
}

修改事件结构:

    public event EventHandler<MessageRecievedEventArgs> MessageRecieved;

    protected virtual void OnMessageReceived(object sender, MessageRecievedEventArgs args)
    {
        var handle = MessageRecieved;

        if (handle == null)
            return;

        if(MainUIThread  != null)
        {
            MainUIThread.Post(d => handle(sender, args), this);
        }
        else
        {
            handle(sender, args);
        }
    }

【讨论】:

    猜你喜欢
    • 2010-12-14
    • 1970-01-01
    • 2012-03-25
    • 1970-01-01
    • 2011-12-24
    • 2014-02-03
    • 2021-06-25
    • 1970-01-01
    • 2012-09-12
    相关资源
    最近更新 更多