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

时间:2012-04-11 12:51:47

标签: c# multithreading events networking invoke

我有一个带有Socket的类,监听客户端以接收数据。当我接收新数据时,我想调用一个事件(如果已实现),但是你知道每个连接都有自己的线程,所以事件将在该线程运行,你知道其余的。你不能使用表单控件。   如何调用事件(或调用它)。我是线程和网络编程的新手,所以我很欣赏任何一个例子。

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)

    }

}
谢谢。

4 个答案:

答案 0 :(得分:1)

如果要从非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();
    }
}

请参阅herehere

答案 1 :(得分:0)

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

答案 2 :(得分:0)

您可以使用典型的marshling操作(如InvokeBeginInvoke)将委托的执行注入UI线程。只需将ISynchronizeInvokeSynchronizationContext的实例传递给您的班级,以便进行整理。

但是,在你的情况下,我不会这样做。因为,无论如何,这些回调都是因为套接字事件而发生的,所以可能可能会变得艰难而沉重。你绝对不想用你所有的活动来抨击你的UI线程。相反,将所有相关数据打包并放入一个集合,然后UI线程可以在更合理的时间间隔内使用System.Windows.Forms.Timer进行轮询。

我一直在抨击这些严厉的行动。他们被高估和过度使用。请记住,有两种在UI和工作线程之间共享数据和信令的通用方法。

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

拉方法可以,而且往往更优雅。

答案 3 :(得分:0)

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