调用在 C# 中的其他线程上实现的事件

本文关键字:实现 事件 线程 其他 调用 | 更新日期: 2023-09-27 18:30:49

我有一个带有套接字的类,侦听客户端接收数据。当接收新数据时,我想调用一个事件(如果实现),但如您所知,每个连接都有自己的线程,因此事件将在该线程上运行,而您知道其余的。 不能使用窗体控件。 如何调用事件(或调用它)。我对线程和网络编程真的很陌生,所以我很欣赏任何例子。

public class HVremotechooser
{
    public delegate void NewOrder(Order order);
    public event NewOrder nOrder;
    //... (code elided)

    public void ReceiveCallback(IAsyncResult AsyncCall)  // new connection of client
    {
         //... (code elided)
         if (nOrder != null)
              nOrder(Order);   // calling the event "nOrder"
         //... (code elided)
    }
}

谢谢。

调用在 C# 中的其他线程上实现的事件

如果要从非 UI 线程更新窗体,则必须调用该操作。我通常做的是:

private void LongRunningBackgroundThread() {
   // lots of work
   ...
   // Update my form
   InvokeIfRequired(() => {
       ...update form...
   }
}
private static void InvokeIfRequired(Action a) {
    if (control.InvokeRequired) {
        control.Invoke(a);
    } else {
        a();
    }
}

看这里和这里

我在

上周处理的Silverlight应用程序中遇到了类似的问题,并使用了Dispatcher.BeginInvoke方法。 对于Windows表单,看起来使用Control.BeginInvoke可能更容易(尽管我相信两者都应该有效 http://msdn.microsoft.com/en-us/library/system.windows.forms.control.begininvoke.aspx):

可以使用

典型的封送处理操作(如 InvokeBeginInvoke)将委托的执行注入到 UI 线程上。 只需将 ISynchronizeInvokeSynchronizationContext 的实例传递给您的类即可简化封送处理。

但是,在您的情况下,我不会这样做。由于无论如何,这些回调可能是由于套接字事件而发生的,因此它们很可能是硬而重的。您绝对不想用所有这些活动猛击您的 UI 线程。相反,应打包所有相关数据并放入集合中,然后 UI 线程可以轮询该集合以更合理的间隔使用System.Windows.Forms.Timer

我一直在撕毁这些沼泽作业。它们被高估和过度使用。请记住,有两种常规方法可以在 UI 和工作线程之间共享数据和发出信号。

  • 通过工作线程中的InvokeBeginInvoke推送方法
  • 通过 UI 线程中的System.Windows.Forms.Timer拉取方法

拉动方法可以而且通常更优雅。

UI

线程是一个 UI 问题。 在我看来,您不必担心在此代码中调用 ui 线程。 相反,事件的使用者应该做Invoke或他们碰巧需要做的任何其他线程操作。这样,如果 UI 人员需要更改他们的策略(例如,通过使用计时器),您的非 UI 相关代码就不需要更改。