複数のバックグラウンドワーカー(.net/c#内)を呼び出すメインスレッドがあります。 これらのスレッドのそれぞれは、実行可能ファイルを実行するためにプロセスを開始します。 プロセスが終了すると、メインスレッドに他のすべてのスレッドとそれぞれのプロセスを強制終了するように指示します。それらのすべてが停止した後、私はこれを知り、後処理のためにメインスレッドを実行し続ける必要があります。
これらの外部プロセスのリストを保持していますので、それらをすべて削除することに問題はありません。私の問題は、これらのすべてのバックグラウンド労働者を殺す方法です。 runworkercompletedメソッドがまだ複数回呼び出されているため、終了した最初のスレッド内からスレッドのリストを保持して終了させようとしました。 誰かが良い方法でそれらの労働者を殺す方法のパターンを持っていますか?私は何とか他の労働者の殺害を行うためにメインスレッドに通知する必要がありますか?複数のバックグラウンドワーカーの終了
答えて
this answerから、Backgroundworkerを殺す方法はないようです。しかし、this answerは、OnDoWork
を無効にし、Thread.CurrentThread
という参照を残して回避策を示しています。私はまだそれらのバックグラウンドワーカーにキャンセル通知をチェックさせようとします。
async/awaitとCancellationTokenSourcesの使用をお勧めします。私はBackgroundWorkersの使い方についてアドバイスをしますが、async/awaitははるかに便利で短くなるので、まずそれが優先されます。
async/awaitは、はるかに複雑さを増やすことなく、探している機能を提供するので便利です。
private async Task DoSomething(CancellationToken token)
{
// Do stuff
// Periodically check if someone has finished
if (Token.IsCancellationRequested)
{
// clean up
return;
}
}
非同期/コードは、いくつかの落とし穴、including deadlockを持って待っています:
private async void SomeEvent(object sender, EventArgs e)
{
CancellationTokenSource cts = new CancellationTokenSource();
var waiter1 = DoSomething(cts.Token);
var waiter2 = DoSomethingElse(cts.Token);
// etc.
// Wait for the first one to finish, then cancel
await Task.WhenAny(waiter1, waiter2, ...).ConfigureAwait(false);
cts.Cancel();
// wait for the remainder to finish
await Task.WhenAll(waiter1, waiter2, ...).ConfigureAwait(false);
// Do Postprocessing
}
あなたの "ウェイターは" このようなものを見て。これは速いプロジェクトのように聞こえるので(私は間違っている可能性があります)、学習するには良い場所のように思えます。特に、大規模なコードベースがなくてもうまくいきます。詳細を知りたい場合は、スティーブン・クレアリーのブログ、特に彼のintroを開始するのがよいと思います。
一方、もしあなたが絶対にあなたがBackgroundWorkersを使いたいと思っているのであれば、私はあなたを責めませんが、私もあなたを羨ましく思いません。
まず、あなたの労働者は、他の誰かが最初に終了したかどうかを知る必要があります。 、そして、
private void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
// Check for errors...
}
else if (e.Cancelled)
{
// Mark that this one has finished
}
else
{
// Assuming you have a set of BackgroundWorkers called "workers"
foreach (var bgw in workers)
bgw.CancelAsync();
// other stuff...
}
}
取り消しを報告してくださいDoWorkメソッドの末尾にコードのビットを追加...
private void DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
// Do stuff...
// When "RunWorkerCompleted" is called, let it know whether this worker has been cancelled.
e.Cancel = worker.CancellationPending;
}
そして、それはそれだ:他人のBackgroundWorkersをキャンセルするために、完成のBackgroundWorkerのRunWorkerCompletedメソッドを使用します。あなたは、あなたが以前に終了することができるかどうかを定期的に確認するためにworker.CancellationPendingを定期的にチェックすることもできますが、復帰前にworker.CancellationPendingをe.Cancelに割り当てることを忘れないでください!
1つ最後のこと:すべての作業者が終了したときに後処理を続行する場合は、特定の作業者が終了したときにマークを付けて(他の作業をキャンセルする)必要があります。彼らがいつ終わったのかを知る方法(後処理を始めることができます)。それは実行可能で、それほど難しくない - 私の頭の上から、私はDictionary<BackgroundWorker, bool>
を使ってどの作業者が終了したのかを示します。それでも、それは非同期/待機で避けることのできるもう一つの混乱です。
- 1. 複数のバックグラウンドワーカー+ C#
- 2. VB.Net複数のバックグラウンドワーカー - 最後のタスクが完了しました
- 3. 複数のアラートを終了するXCUITesing
- 4. データベースクエリの終了/非終了
- 5. イベント終了後の関数
- 6. jQueryの複数の属性終了セレクタ(OR)
- 7. res.render複数のデータクエリが終了した後のみ
- 8. 複数の非同期コールバックの終了を検出します
- 9. シンプルモダル終了関数
- 10. javaScriptは複数のファイルをアップロードする - 終了時に
- 11. シェルが複数の行にファイルを終了するエコー?
- 12. 終了時に複数のシェーダーを削除しますか?
- 13. アプリケーションの終了イベントの終了
- 14. バックグラウンドワーカーが複数の割合を報告している
- 15. プロセスの終了終了を待つ
- 16. SASの中断/終了/終了
- 17. Chisel.TestApplicationException:テストアプリケーションの終了 - 終了コード139
- 18. 複数のバックグラウンドワーカーが完了し、UIスレッドを更新するかどうかを確認する方法?
- 19. ストリームイベント:終了vs終了
- 20. 終了関数定義(アルゴリズム)
- 21. タイマー終了時に複数回ポップアップするアラートウィンドウ
- 22. Androidソフトキーボード:「終了」の「完了」
- 23. アクティビティの終了
- 24. アプリケーションの終了
- 25. プロジェクトの終了
- 26. リミットウェブページの終了
- 27. メインの関数を終了する
- 28. データベーストランザクションのオープンと終了グローバル変数
- 29. Rubyシステムの終了ステータス定数
- 30. Angular 2アニメーション終了コールバック関数の例
スレッド/プロセスの作成方法と開始方法のコードを投稿すると便利です –