跟踪并发任务

时间:2012-07-24 20:46:34

标签: multithreading c#-4.0 collections

我正在编写一个针对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属性来识别集合中的项目,但我不相信我可以处理任务本身内集合中的任务对象;另请注意,该集合必须是线程安全的。

如果我在任务之外(在主线程中)放置某种清理代码,我就不需要线程安全集合,但我不知道任务何时在主线程中完成。

那么,我应该使用哪个集合来维护并发任务的列表/数组,以便我可以使用WaitAny(),如何在完成后清理列表?

1 个答案:

答案 0 :(得分: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);     
    }  
}