2010-12-01 75 views
4

我有一个使用包含线程的类的窗体的C#2.0应用程序。从线程调用Invoke/BeginInvoke

在线程函数中,不是直接调用事件处理函数,而是调用它。其效果是拥有窗体不需要调用InvokeRequired/BeginInvoke来更新其控件。

public class Foo 
{ 
    private Control owner_; 
    Thread thread_; 

    public event EventHandler<EventArgs> FooEvent; 

    public Foo(Control owner) 
    { 
     owner_ = owner; 
     thread_ = new Thread(FooThread); 
     thread_.Start(); 
    } 

    private void FooThread() 
    { 
     Thread.Sleep(1000); 
     for (;;) 
     { 
      // Invoke performed in the thread 
      owner_.Invoke((EventHandler<EventArgs>)InternalFooEvent, 
       new object[] { this, new EventArgs() }); 
      Thread.Sleep(10); 
     } 
    } 

    private void InternalFooEvent(object sender, EventArgs e) 
    { 
     EventHandler<EventArgs> evt = FooEvent; 
     if (evt != null) 
      evt(sender, e); 
    } 
} 

public partial class Form1 : Form 
{ 
    private Foo foo_; 

    public Form1() 
    { 
     InitializeComponent(); 

     foo_ = new Foo(this); 
     foo_.FooEvent += OnFooEvent; 
    } 

    private void OnFooEvent(object sender, EventArgs e) 
    { 
     // does not need to call InvokeRequired/BeginInvoke() 
     label_.Text = "hello"; 
    } 
} 

这显然是违背了使用后台线程像System.Timers.Timer和System.Io.Ports.SerialPort微软的API使用的方法。这种方法有什么内在的错误吗?某种方式危险吗?

感谢, PaulH


编辑:另外,如果表单没有订阅什么事件,对吗?它会阻塞表单的消息队列中的表单不感兴趣的事件吗?

+0

请看我的编辑 – Falcon 2010-12-01 18:35:19

回答

3

这是一个线程安全调用,该方法将在窗体的线程中处理。

从概念的角度来看它没什么不妥。

尽管如此,定时器对于这样的任务更加优雅。但是,间隔10ms的定时器可能会减慢GUI的速度,这可能是Invoke被使用的原因。

您不需要调用InvokeRequired,因为很明显控件位于另一个线程中。另外,当你想异步调用一个方法时,只需要调用BeginInvoke,这显然不是这种情况。

关于您的编辑: 不,消息队列不会被堵塞。如果没有注册处理程序,则不会触发任何事件。再看看你的代码;)