2010-12-01 16 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などのバックグラウンドスレッドを使用して、MicrosoftのAPIで使用される方法に反しています。本質的にこの方法に間違いがありますか?それは何らかの形で危険ですか?

おかげで、 PaulH


編集:また、フォームがすぐにイベントに何を購読していない場合は?それはフォームが興味を持たないイベントでフォームのメッセージキューを詰まらせるでしょうか?

+0

私の編集を参照してください – Falcon

答えて

3

これはスレッドセーフな呼び出しで、メソッドはフォームのスレッドで処理されます。

概念的な視点から見ても問題ありません。

タイマーは、このようなタスクの方がより洗練されています。しかし、10ms間隔のタイマーがGUIの速度を落とす可能性があります。これはおそらくInvokeが使用された理由です。

Controlが別のスレッドにあることが明確であるため、InvokeRequiredを呼び出す必要はありません。また、BeginInvokeはメソッドを非同期に呼び出す場合にのみ呼び出す必要があります。これは明らかにここでは当てはまりません。

編集に関する: いいえ、メッセージキューが詰まることはありません。ハンドラが登録されていなければ、イベントは発生しません。あなたのコードをもう一度見てください;)

関連する問題