2010-11-24 35 views
4

私はさらに非同期タスクを呼び出す必要がある非同期操作に取り組んでいます。 BackgroundWorkersを使用することでシンプルにしています。その結果、BackgroundWorkerのDoWork()コールバックは、2番目のBackgroundWorkerを作成するメソッドを呼び出します(エラーチェックを省略し、すべてのジャズを簡潔にする)。ネストされたBackgroundWorkers:間違ったスレッドでRunWorkerCompletedが呼び出されましたか?

問題は、私はClass2._Worker_RunWorkerCompleted()がClass2.DoSomethingElseAsync()が呼び出された同じスレッドで実行されることを期待しています。これは決して起こりません。代わりに、全く新しいスレッドでコールバックが実行されます。

Class1の_worker_DoWork()は返されません。これはスレッドが存在していても、スレッドがイベントリスナーに戻ってこないことを意味します。一方、_worker_DoWork()が返された場合、Class1のBackgroundWorkerは自動的に途中で終了するため、Class2が作業を終了するまでClass2が終了するまで待つ必要があります。二つの質問につながる

  1. は正しい私の疑いですか?
  2. このような非同期操作をネストする最も良い方法は何ですか? BackgroundWorkerのアプローチを救済することはできますか、それとも他のより適切な手法がありますか?

答えて

5

BackgroundWorkerがUIスレッドで作成された場合、DoWorkはスレッドプールスレッドで実行され、RunWorkerCompletedはUIスレッドで実行されます。

DoWorkは、スレッドプールプールでも実行され、RunWorkerCompletedはスレッドプールスレッドでも実行されます(UIスレッドではない)。

場合によっては、任意の(スレッドプール)スレッドへの呼び出しをマーシャリングできないため、希望の動作を保証することはできませんが、System.Threading.SynchronizationContextを参照してください。

+0

ありがとう、それは間違いなく正しい方向に私を指摘しました。このジョブを処理するには、「イベントベースの非同期パターン」(http://msdn.microsoft.com/en-us/library/wewwczdw%28v=VS.90%29.aspx)を実装する必要があります。これは、BackgroundWorkerの代わりにAsyncOperationクラスを使用するため、メッセージがどの同期コンテキストに送られるかをいくらか制御できます。 –

0

、私は実際に労働者の実行を開始することをどこでも見ることができません。あなたは

public void DoSomethingAsync() 
{ 
    _worker = new BackgroundWorker(); 
    _worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_worker_RunWorkerCompleted); 
    _worker.DoWork += new DoWorkEventHandler(_worker_DoWork); 
    _worker.RunWorkerAsync(); // add this line to start it 
} 

第二に、作業ハンドラ(_worker_DoWorkメソッドは)DoSomethingAsyncへの呼び出しと同じスレッドであることが保証されていません(また、クラス2にDoSomethingElseAsyncメソッドの呼び出しを追加)DoSomethingAsync方法を変更することができます - これはバックグラウンドワーカーの全ポイントです。すなわち、/別のスレッドで作業を行う。ワーカー・ハンドラ・ハンドラ(_worker_RunWorkerCompletedメソッド)も同様です。

最後に、トップレベルのもの(Class1)が常にClass2の作業を必要としない限り、2人の異なるバックグラウンドワーカーを付けても意味がないようです。それぞれのバックグラウンドワーカーを1人のマネージャーで処理する方がよいでしょう。

+0

申し訳ありませんが、私はRunWorkerAsync()呼び出しを入力するのを忘れましたが、実際のコードの中にあります。外側の労働者は、第2の労働者を制御する必要があります。内部作業者の作業をいつ、どのように行う必要があるかを決定するためのコードは、外部作業者のDoWorkメソッドで行われます。 –

関連する問題