使用任务并行库

时间:2014-11-17 17:39:34

标签: c#

我刚开始编写和使用.NET 4.5中的TPL,并想知道你是否可以帮助我。

基本上,我的WPF程序对一组数据库记录执行繁重的工作,这些记录可能在500万到1000万之间。 我想利用TPL库有效地管理这项工作,同时保持UI响应。

我的方案如下,我计划使用3个单独的任务来检索每个300万的数据,并将它们提供给我的工作人员#34;。

我想要一个单独的任务,从上述任务中获取所有项目中的每个项目,并使用它。

所以我想要一个全局列表的项目,所有3个任务都可以放入项目,我的第四个任务,然后应该从这个主列表中一次一个地选择项目并做一些工作,它应该等待列表是空了以便再次填满等。

您能否就TPL如何做到这一点提供一些指导?我是TPL的新手。一些示例代码会很好。

2 个答案:

答案 0 :(得分:1)

考虑将每个Task中的项目存储在全局的线程安全列表对象中,例如ConcurrentStackConcurrentQueue

有关详细信息,请参阅:http://msdn.microsoft.com/en-us/library/system.collections.concurrent(v=vs.110).aspx

答案 1 :(得分:1)

如果我正确理解了问题描述,你就有了一个生产者/消费者场景,其中有三个生产者,每个生产者从数据库中检索独立的记录,以及一个消费者。

如果是这种情况,那么在我看来,你想要从BlockingCollection<T>开始,其中T是生产者从数据库中检索的对象类型。要使用的基础集合取决于您希望如何处理数据。最常见的场景是FIFO和无序,分别由ConcurrentQueue<T>ConcurrentBag<T>表示。

这是一个简单的代码示例,演示了如何工作:

BlockingCollection<int> consumeFrom = new BlockingCollection<int>();
int producerCount = 3;

for (int i = 0; i < producerCount; i++)
{
    int taskValue = i;

    // Make dummy task for example
    Task.Run(() =>
    {
        for (int j = 0; j < 10; j++)
        {
            Thread.Sleep(1000);
            consumeFrom.Add(taskValue * 10 + j);
        }

        if (Interlocked.Decrement(ref producerCount) == 0)
        {
            consumeFrom.CompleteAdding();
        }
    });
}

foreach (int i in consumeFrom.GetConsumingEnumerable())
{
    Console.WriteLine(i);
}

请注意,这使用ConcurrentQueue<T>的默认基础数据源。您可以向IProducerConsumerCollection<T>构造函数提供BlockingCollection<T>的其他实现,例如:

BlockingCollection<int> consumeFrom =
    new BlockingCollection<int>(new ConcurrentBag<int>());