我刚开始编写和使用.NET 4.5中的TPL,并想知道你是否可以帮助我。
基本上,我的WPF程序对一组数据库记录执行繁重的工作,这些记录可能在500万到1000万之间。 我想利用TPL库有效地管理这项工作,同时保持UI响应。
我的方案如下,我计划使用3个单独的任务来检索每个300万的数据,并将它们提供给我的工作人员#34;。
我想要一个单独的任务,从上述任务中获取所有项目中的每个项目,并使用它。
所以我想要一个全局列表的项目,所有3个任务都可以放入项目,我的第四个任务,然后应该从这个主列表中一次一个地选择项目并做一些工作,它应该等待列表是空了以便再次填满等。
您能否就TPL如何做到这一点提供一些指导?我是TPL的新手。一些示例代码会很好。
答案 0 :(得分:1)
考虑将每个Task
中的项目存储在全局的线程安全列表对象中,例如ConcurrentStack
或ConcurrentQueue
。
有关详细信息,请参阅: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>());