调用跨线程事件的最干净方法

时间:2020-03-05 18:42:01  来源:igfitidea点击:

我发现.NET事件模型是如此,我经常会在一个线程上引发一个事件,然后在另一个线程上监听它。我想知道将事件从后台线程封送到我的UI线程的最干净方法是什么。

根据社区的建议,我使用了以下方法:

// earlier in the code
mCoolObject.CoolEvent+= 
           new CoolObjectEventHandler(mCoolObject_CoolEvent);
// then
private void mCoolObject_CoolEvent(object sender, CoolObjectEventArgs args)
{
    if (InvokeRequired)
    {
        CoolObjectEventHandler cb =
            new CoolObjectEventHandler(
                mCoolObject_CoolEvent);
        Invoke(cb, new object[] { sender, args });
        return;
    }
    // do the dirty work of my method here
}

解决方案

回答

我回避了多余的委托人声明。

private void mCoolObject_CoolEvent(object sender, CoolObjectEventArgs args)
{
    if (InvokeRequired)
    {
        Invoke(new Action<object, CoolObjectEventArgs>(mCoolObject_CoolEvent), sender, args);
        return;
    }
    // do the dirty work of my method here
}

对于非事件,可以使用System.Windows.Forms.MethodInvoker委托或者System.Action。

编辑:此外,每个事件都有一个对应的EventHandler委托,因此根本不需要重新声明一个。

回答

我一直想知道总是假设需要调用是多么昂贵...

private void OnCoolEvent(CoolObjectEventArgs e)
{
  BeginInvoke((o,e) => /*do work here*/,this, e);
}

回答

一些观察:

  • 除非我们是2.0之前的版本,否则不要在这样的代码中显式创建简单的委托,因此可以使用:
BeginInvoke(new EventHandler<CoolObjectEventArgs>(mCoolObject_CoolEvent), 
               sender, 
               args);
  • 另外,我们不需要创建和填充对象数组,因为args参数是" params"类型,因此我们只需传递列表即可。
  • 我可能更喜欢Invoke而不是BeginInvoke,因为后者将导致异步调用代码,这可能不是我们所追求的,但是如果不调用EndInvoke,将使后续异常难以传播。将会发生的事情是,应用最终将获得" TargetInvocationException"。

回答

我们可以尝试开发某种通用组件,该组件接受SynchronizationContext作为输入并使用它来调用事件。

回答

有趣的是,WPF的绑定会自动处理封送处理,因此我们可以将UI绑定到在后台线程上修改的对象属性,而无需执行任何特殊操作。事实证明,这对我来说是一个很好的节省时间的方法。

在XAML中:

<TextBox Text="{Binding Path=Name}"/>

回答

我在网上有一些代码。比其他建议要好得多。一定要检查出来。

用法示例:

private void mCoolObject_CoolEvent(object sender, CoolObjectEventArgs args)
{
    // You could use "() =>" in place of "delegate"; it's a style choice.
    this.Invoke(delegate
    {
        // Do the dirty work of my method here.
    });
}

回答

我认为最干净的方法肯定是走AOP路线。做几个方面,添加必要的属性,我们不必再次检查线程亲和力。