SQL Server に対するポーリング システムを作成しています。タスクが取得されると、 を使用して新しいスレッドにオフロードされますTask.Factory.StartNew()
。全体が無限ループ内にあり、N 個の同時タスクのみを許可したいと考えています。
while(true)
{
// create connection
while(_concurrentTasks < _allowedTasks)
{
// get job info
if(!reader.HasRows) break; // no work to do.
while(reader.Read())
{
// fill JobInfo entity from reader
_taskCollection.Add(Task.Factory.StartNew(() => ProcessJob(jobInfo)));
_concurrentTasks++;
}
}
// could break for 1 of 2 reasons, threshold met or nothing to do
if((_concurrentTasks < _allowedTasks)
{
// sleep for a predetermined period of time
Thread.Sleep(60000);
}
else
{
// wait for one thread to complete and then get more jobs
Task.WaitAny(_taskCollection.ToArray);
}
}
この状況でどのコレクションを使用するのが最適か、または完了したタスクをクリーンアップする方法がわかりません。
クリーンアップ コードをタスク自体に配置するList<Task>
と、プロパティと共に使用Task.CurrentId
してコレクション内のアイテムを識別できますが、コレクション内の Task オブジェクトをタスク自体内で破棄できるとは思えません。コレクションはスレッドセーフでなければならないことにも注意してください。
ある種のクリーンアップ コードをタスクの外 (メイン スレッド) に配置すると、スレッド セーフなコレクションは必要なくなりますが、メイン スレッドでタスクがいつ完了するかはわかりません。
では、同時実行タスクのリスト/配列を維持するためにどのコレクションを使用すればよいWaitAny()
のでしょうか?また、完了時にリストをクリーンアップするにはどうすればよいでしょうか?