8

私は小さなチャットアプリを書いていて、このイベントハンドラーがあります:

void o_Typing(object sender, EventArgs e)
{
    MessageBox.Show("Fired!");
    this.Text = "Fired!";
}

o_Typingから派生したクラスのメソッドTabPageです。基本的に、各会話には独自のタブが必要です。

イベント ハンドラーは、別のスレッドで実行されている Chat オブジェクトによって起動されます。UI 用に 1 つのスレッドがあり、チャットの会話ごとに別のスレッドがあります (新しいデータについてサーバーをポーリングし続けるため)。

イベントが発生すると、MessageBoxポップアップが表示されますが、タブのキャプションは変更されません。イベントが一度発生すると、二度と発生しないため、UI スレッドで定義されているにもかかわらず、イベントがワーカー スレッドで呼び出されていると思われます。

Invoke()イベントをワーカー スレッドから呼び出して、UI スレッドで実行するために使用するにはどうすればよいですか?

4

2 に答える 2

10

次の 2 つのオプションがあります。

1) イベント ハンドラーをスレッド セーフにする: Control.Invoke/BeginInvokeUI スレッドと通信する必要があるイベント ハンドラーで使用します。

2) イベントを発生させる前に、ワーカー スレッドを UI スレッドにマーシャリングします。つまり、Control.Invokeイベントを発生させるプロセスの一部として使用して、イベント ハンドラーがすべて UI スレッドで呼び出されるようにします。ISynchronizeInvokeアプリの構造によっては、イベントを発生させるコンポーネントに UI を明示的に認識させたくない場合がControlあります。右のスレッド。もちろん、これはすべてのイベント ハンドラが同じスレッドで実行できる場合にのみ (単純に) のみ機能しますが、多くの場合、これは当てはまります。次のように書きます。

protected void OnFoo(EventArgs args)
{
    if (sync != null && sync.InvokeRequired)
    {
        sync.Invoke((Action) delegate { OnFoo(args) }, null);
        return;
    }
    EventHandler handler = Foo; // Where Foo is the event name
    if (handler != null)
    {
        handler (this, args);
    }
}
于 2009-07-01T06:24:20.410 に答える
5

ワーカー スレッドによって実行されるコードでイベントを発生させると、イベントに登録されているすべてのメソッドがそのワーカー スレッドで実行されます。

GUI 要素については、Invoke メソッドを確認する必要があります。

よろしくお願いします

于 2009-07-01T06:18:50.310 に答える