2010-06-22 77 views
3

我正在编写Windows窗体应用程序。它有一个线程来执行一些操作,当操作发现它必须通知主窗体来更改控件时。如何在C#中提高事件 - 最佳方法

目前通知使用下列MSDN页面hadling描述的C#事件: http://msdn.microsoft.com/en-us/library/wkzf914z(VS.71).aspx

但我不知道该委托。由于我在上面描述的情况,线程调用委托。这是一个线程安全的方法来提高事件吗?

在C#中实现Windows消息(SendMessage)是否更好,然后在WindowProc中实现消息处理程序。

欣赏你在这个时间。

+0

您使用的是.NET 1.1吗?如果没有,那么你不应该使用.NET 1.1文档。改为使用http://msdn.microsoft.com/en-us/library/wkzf914z.aspx。 – 2010-06-22 05:04:16

回答

4

除非您需要对线程进行非常好的控制,否则可以使用BackgroundWorker。它为您处理所有的跨线程通信。你基本上把你的后台代码放在它的DoWork事件处理器中,然后通过ProgressChanged和RunWorkerCompleted事件将数据传回UI线程。上面的链接有一个完整的例子来说明如何使用它。

但是一般来说,只要你遵循一些基本的指导原则,简单地添加事件处理程序和引发事件就是线程安全的。但是,事件处理程序将在引发事件的代码的同一线程上调用。事件处理代码可能不期望在后台线程上调用,因此这就是BackgroundWorker派上用场的地方。

以下是以线程安全方式引发事件的类的非常基本的框架。处理事件的代码是否是线程安全的完全是另一回事。

class MyClass { 

    public event EventHandler SomethingHappened; 

    protected virtual void OnSomethingHappened(EventArgs e) { 
     EventHandler handler = SomethingHappened; 
     if (handler != null) { 
      handler(this, e); 
     } 
    } 

    public void DoSomething() { 
     OnSomethingHappened(EventArgs.Empty); 
    } 

} 
+0

嗨乔希, 谢谢你的回复。 在C#中实现Windows消息(SendMessage)是否更好,然后在WindowProc中实现消息处理程序? 请让我知道。 再次感谢。 – 2010-06-22 04:29:40

+1

不,这在.NET中不是必需的。将调用发布到UI线程有更好的方法。其中之一是BackgroundWorker,它在内部使用一个名为SynchronizationContext的类。另一种方法是使用任何控件的BeginInvoke方法。 Windows Forms基础结构隐藏了您的所有WndProc goo。如果你直接使用它,那么你将会重新实现许多免费获得的东西。 – Josh 2010-06-22 04:33:41

0

委托方法并不全是坏事,但问题在于事件调用另一个线程中的事件处理程序。这狐狸你的UI更新,这需要在主线程中完成。所以你可以在事件处理程序中适当地使用InvokeRequired。

void OnStatusMessage(string s) 
{ 
    // might be coming from a different thread 
    if (txtStatus.InvokeRequired) 
    { 
    this.BeginInvoke(new MethodInvoker(delegate() 
    { 
     OnStatusMessage(s); 
    })); 
    } 
    else 
    { 
    StatusBox.Text += s + "\r\n"; 
    StatusBox.SelectionStart = txtStatus.TextLength; 
    StatusBox.ScrollToCaret(); 
    } 
} 

当使用BackgroundWorker作为Josh提到时,这可能不是必需的。但是,如果您正在考虑ThreadPool和WaitCallBack(*)来管理线程,它会很有用。

使用Windows消息的一个问题是,您必须知道将消息发送到哪个窗口,并且多个订阅者更加痛苦。 (对于你只需+ =另一个处理程序的事件)

  • 我无法发布超链接的WaitCallBack,因为我还没有多链接谱系。