作業を生成する 1 つのプロセスと、BlockingCollection<>
その作業を消費する 2 番目のプロセスがあります。プログラムを閉じるときは、コンシューマーが作業を消費するのを止める必要がありますが、保留中だったが消費されていない作業をすばやくログに記録する必要があります。
foreach (<object> in BlockingCollection.GetConsumingEnumerable())
現在、私の消費者はループを持つスレッドを生成しています。プログラムを停止すると、プロデューサーが を呼び出しますConsumer.BlockingCollection.CompleteAdding()
。私が見つけたのは、私の消費者がキュー内のすべてを処理し続けていることです。
問題をグーグルで検索すると、CancellationToken
. だから私はそれを試しました:
private void Process () { // This method runs in a separate thread
try {
foreach (*work* in BlockingCollection.GetConsumingEnumerable(CancellationToken)) {
// Consume
}
}
catch (OperationCancelledException) {
foreach (*work* in BlockingCollection.GetConsumingEnumerable()) {
// quickly log
}
}
}
私のプロデューサーは:
private CancellationTokenSource StopFlag = new CancellationTokenSource ();
MyConsumer.CancellationToken = StopFlag.Token;
// Make the consumer spawn it's consuming thread...
StopFlag.Cancel ();
MyConsumer.BlockingCollection.CompleteAdding ();
これを試してみると、OperationCancelledException が発生したという兆候はありません。
この質問は、キャンセル トークンの使用を説明しようとしていますが、正しく使用されていないようです。(引数:機能する場合、それは「十分に正しい」です。)そして、この質問は私の質問とまったく同じように見えますが、例はありません。(ここも同じ)
繰り返しになりますが、別の方法を使用してキャンセルされた後、キュー内の残りのアイテムを処理する必要があるという警告とともに、CancellationToken
onを適切に使用するにはどうすればよいですか?BlockingCollection.GetConsumingEnumerable()
(私の問題は、CancellationToken の適切な使用に集中していると思います。私のテストでは、プロセスが実際にキャンセルされていることは示されていません。(StopFlag.IsCancellationRequested
常に等しいfalse
))