次のコードを観察してください。
var handler = GetTheRightHandler();
var bw = new BackgroundWorker();
bw.RunWorkerCompleted += OnAsyncOperationCompleted;
bw.DoWork += OnDoWorkLoadChildren;
bw.RunWorkerAsync(handler);
bw
ここで、作業が完了するまで待ちたいとします。そうする正しい方法は何ですか?
私の解決策はこれです:
bool finished = false;
var handler = GetTheRightHandler();
var bw = new BackgroundWorker();
bw.RunWorkerCompleted += (sender, args) =>
{
OnAsyncOperationCompleted(sender, args);
finished = true;
});
bw.DoWork += OnDoWorkLoadChildren;
bw.RunWorkerAsync(handler);
int timeout = N;
while (!finished && timeout > 0)
{
Thread.Sleep(1000);
--timeout;
}
if (!finished)
{
throw new TimedoutException("bla bla bla");
}
でも、私は嫌いです。
finished
フラグを同期イベントに置き換えて、RunWorkerCompleted
ハンドラーに設定し、スリープ中のループを実行する代わりに後でブロックすることを検討しました。
残念ながら、コードは WPF または WindowsForm 同期コンテキストで実行される可能性があるため、これは間違っていますRunWorkerCompleted
。
より良い解決策を知りたいです。
ありがとう。
編集:
PS
- サンプルコードは、私の質問を明確にするために意図的に工夫されています。私は完了コールバックを完全に認識していますが、完了まで待つ方法を知りたいです。それが私の質問です。
- 私は、、、などを認識してい
Thread.Join
ますDelegate.BeginInvoke
...ThreadPool.QueueUserWorkItem
質問は具体的には に関するものBackgroundWorker
です。
編集2:
わかりました。シナリオを説明すると、はるかに簡単になると思います。
いくつかの非同期コードを呼び出す単体テスト メソッドがあり、最終的にBackgroundWorker
完了ハンドラーを渡すことができる a に関与します。すべてのコードは私のものなので、必要に応じて実装を変更できます。ただし、 を置き換えるつもりはありませんBackgroundWorker
。適切な同期コンテキストが自動的に使用されるため、コードが UI スレッドで呼び出されると、完了コールバックが同じ UI スレッドで呼び出されます。これは非常に優れています。
いずれにせよ、BW が作業を完了する前に単体テスト メソッドが終了する可能性はありますが、これは良くありません。そのため、BW が完了するまで待ちたいのですが、最善の方法を知りたいと考えています。
それにはもっと多くの部分がありますが、全体像は多かれ少なかれ今説明したようなものです.