阻塞集合+每个阻塞集合的多个工作线程+等待工作完成

时间:2014-09-14 19:39:04

标签: c# task-parallel-library blockingcollection

我必须在1000条消息中执行操作,如操作A,B,C。我可以并行执行这些操作。 我为他们创建了组。为了增加并行性,我在每个组中创建了子组。子组中的任务需要串行执行。但是两个子组可以并行执行。 在一批1000次完成之后,我必须做一些处理,即保存在db中。但是我无法理解,如何等待所有的任务完成(我不感兴趣在1000分钟结束时在中间等待)。欢迎任何建议。

public class OrderlyThreadPool<t> : IDisposable
{
    BlockingCollection<t> _workingqueue = null;
    Action<t> _handler = null;
    public OrderlyThreadPool(int wrkerCount, Action<t> handler)
    {
        _workingqueue = new BlockingCollection<t>();
        _handler = handler;
        Worker worker = new Worker(wrkerCount, Process); //WorkerCount is always 1
        worker.Start();
    }

    public void AddItem(t item)
    {
        _workingqueue.Add(item);
    }
    private void Process()
    {
        foreach (t item in _workingqueue.GetConsumingEnumerable())
        {
            _handler(item);
        }
    }
    public void Dispose()
    {
        _workingqueue.CompleteAdding();
        _workingqueue = null;
    }

}

public class Worker
{
    int _wrkerCount = 0;
    Action _action = null;
    public Worker(int workerCount, Action action)
    {
        _wrkerCount = workerCount;
        _action = action;

    }
    public void Start()
    {
        // Create and start a separate Task for each consumer:
        for (int i = 0; i < _wrkerCount; i++)
        {
            Task.Factory.StartNew(_action);
        }
    }
}

所以基本上我会为每个子组创建OrderlyThreadPool。 我是来自来源的recv消息,如果没有消息可用则会阻止。所以我的代码看起来像

while(true)
{

    var message = GetMsg();

    foreach(OrderlyThreadPool<Msg> a in myList)
    {
        a.AddMsg(message);

    }

    if(msgCount > 1000)
    {
    Wait for all threads to finish work;

    }
    else
    {
    msgCount =msgCount+1;

    }

}

1 个答案:

答案 0 :(得分:0)

您开始执行任务但不保留参考。只需存储这些任务,通过Worker和OrderlyThreadPool公开它们,并使用Task.WhenAll等待所有这些任务完成:

public class Worker
{
    //...
    List<Task> _tasks = new List<Task>();
    public Task Completion { get { return Task.WhenAll(_tasks); } }
    public void Start()
    {
        // Create and start a separate Task for each consumer:
        for (int i = 0; i < _wrkerCount; i++)
        {
            Tasks.Add(Task.Factory.StartNew(_action));
        }
    }
}

public class OrderlyThreadPool<t> : IDisposable
{
    //...
    public Task Completion { get { return _worker.Completion; }}
}

await Task.WhenAll(myList.Select(orderlyThreadPool => orderlyThreadPool.Completion));

但是,您应该考虑使用TPL Dataflow。它是一个基于actor的框架,它封装了完成,批处理,并发级别等等......