0

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()のでしょうか?また、完了時にリストをクリーンアップするにはどうすればよいでしょうか?

4

1 に答える 1

0

配列を使用して、必要に応じてループすることにしました。

Task[] tasks = new Task[_allowedTasks];

while(true)  
{  
    // create connection  

    while(_concurrentTasks < _allowedTasks)  
    {   
        // get job info  

        if(!reader.HasRows) break; // no work to do.  

        while(reader.Read())  
        {  

            for (int i = 0; i < tasks.Length; i++)
            {
                if (tasks[i] == null || tasks[i].IsCompleted)
                {
                    // Dispose of Task at position i

                    nextSlot = i;
                    break;
                }
            }

            // fill JobInfo entity from reader  

            tasks[nextSlot] = 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);     
    }  
}  
于 2012-07-25T09:56:34.097 に答える