.NET 4.0以降を使用している場合は、直接スレッド化するよりもTPLを使用することをお勧めしBlockingCollection<T>
ます。また、UIがコレクションを介して「作業を行う」ことができる方法として、を使用することをお勧めします。
Task
コンシューマーは、 (ここでもTPLから)長時間実行される可能BlockingCollection<T>
性があります。このようにして、スリープやそのような手動のアーティファクトは必要ありません。これによりBlockingCollection<T>
、一定期間の待機をブロックできます。時間、そしてアイテムが消費する準備ができたら再開します。
したがって、キャンセルトークンのソース、ブロックコレクション、およびタスクを次のように定義できます。
private BlockingCollection<Transaction> _bin = new BlockingCollection<Transaction>();
private CancellationTokenSource _tokenSource = new CancellationTokenSource();
private Task _consumer;
また、コンシューマーメソッドは次のように定義できます。
private void ConsumeTransactions()
{
// loop until consumer marked completed, or cancellation token set
while (!_bin.IsCompleted && !_tokenSource.Token.IsCancelRequested)
{
Transaction item;
// try to take item for 100 ms, or until cancelled
if (_bin.TryTake(out item, 100, _tokenSource.Token)
{
// consume the item
}
}
}
次に、フォームが読み込まれたときに、次のようにしてタスクを実行します。
// when you have a task running for life of your program, make sure you
// use TaskCreationOptions.LongRunning. This typically sets up its own
// dedicated thread (not pooled) without having to deal with threads directly
_consumer = Task.Factory.StartNew(ConsumeTransactions, _tokenSource.Token,
TaskCreationOptions.LongRunning, TaskScheduler.Default);
次に、次の手順でアイテムを追加します。
_bin.TryAdd(someTransaction);
Transaction
実行する作業単位を定義するものはどこにありますか...
そして最後に、アプリケーションがシャットダウンしたい場合、次のことができます。
_bin.CompleteAdding();
これは、これ以上アイテムがキューに追加されないことをコンシューマーに通知します。これにより、がTryTake()
返さfalse
れ、ループ_bin.IsCompleted
が終了しますtrue
。
長時間実行されているタスクは、キャンセルトークン(TPLも)がシャットダウンするように設定されるまで、ブロッキングgetをループできます...