简体   繁体   English

使用任务并行库

[英]Using the Task Parallel Library

Im just starting out writing and using the TPL in .NET 4.5 and was wondering if you could help me. 我刚刚开始在.NET 4.5中编写和使用TPL,并且想知道您是否可以帮助我。

Basically, my WPF program performs heavy duty work over a set of database records which could be in the range of 5 to 10 million. 基本上,我的WPF程序对一组可能在5到1000万之间的数据库记录执行繁重的工作。 I want to make use of the TPL library to efficiently manage this work while keeping the UI responsive. 我想利用TPL库有效地管理这项工作,同时保持UI响应。

My scenario is as follows, I was planning on using 3 separate tasks to retrieve data of say 3 million each, and feed them to my "worker". 我的情况如下,我计划使用3个单独的任务来检索每个说300万个的数据,并将其提供给我的“工人”。

And I want a separate task that takes each item from ALL the items from the above tasks and does some work with it. 我想要一个单独的任务,将上述任务中所有项目中的每个项目都提取出来,并对其进行一些处理。

So i want a global List of items that all 3 tasks can put items in, my fourth task, should then pick items from this master list one at a time and do some work with it, it should wait if the list is empty for it to be filled up again etc. 所以我想要一个全局的项目列表,所有三个任务都可以放入项目,这是我的第四个任务,然后应该一次从该主列表中选择一个项目并对其进行一些处理,如果该列表为空,则应该等待再次填充等

Could you please provide some guidance on how to do this with TPL? 您能否提供一些有关如何使用TPL进行操作的指南? I am a newbie with the TPL. 我是TPL的新手。 Some sample code would be good. 一些示例代码会很好。

Consider storing your items from each Task in a global, thread-safe list object, like a ConcurrentStack or ConcurrentQueue . 考虑将每个Task中的项目存储在一个全局的线程安全列表对象中,例如ConcurrentStackConcurrentQueue

For more info, see: http://msdn.microsoft.com/en-us/library/system.collections.concurrent(v=vs.110).aspx 有关更多信息,请参见: http : //msdn.microsoft.com/zh-cn/library/system.collections.concurrent(v=vs.110).aspx

If I understand the problem description correctly, you have a producer/consumer scenario where there are three producers, each retrieving independent records from a database, and a single consumer. 如果我正确理解问题描述,那么您将遇到一个生产者/消费者方案,其中有三个生产者,每个生产者都从数据库中检索独立的记录,并且只有一个消费者。

If this is the case, then it seems to me that you want to start with BlockingCollection<T> , where T is the type of object the producers are retrieving from the database. 如果是这种情况,那么在我看来,您想从BlockingCollection<T> ,其中T是生产者从数据库中检索到的对象的类型。 The underlying collection to use depends on how you want to process the data. 使用的基础集合取决于您如何处理数据。 Most common scenarios are FIFO and unordered, represented by ConcurrentQueue<T> and ConcurrentBag<T> , respectively. 最常见的场景是FIFO和无序,分别由ConcurrentQueue<T>ConcurrentBag<T>

Here's a simple code example that demonstrates how that would work: 这是一个简单的代码示例,演示了如何工作:

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);
}

Note that this uses the default underlying data source of ConcurrentQueue<T> . 请注意,这使用了ConcurrentQueue<T>的默认基础数据源。 You can provide other implementations of IProducerConsumerCollection<T> to the BlockingCollection<T> constructor, eg: 您可以将IProducerConsumerCollection<T>其他实现提供给BlockingCollection<T>构造函数,例如:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM