将生产者和消费者与内部状态

时间:2016-03-24 14:33:24

标签: c# .net task-parallel-library

我想知道以下方法是否是在C#.NET 4.6.1中实现生产者和消费者模式的好方法

我想做什么的说明:
我想读取文件,对数据进行计算并保存结果。每个文件都有一个源(一个设备,例如数据记录器),根据该来源,应该使用不同的计算和输出格式。该文件包含不同的值,例如几个传感器的温度读数。计算具有状态是很重要的。例如,这可能是先前计算的最后一个值,例如,如果我想总结一个原点的所有值。 我想并行处理每个来源的处理。一个来源的所有文件需要按顺序处理(或按时间顺序更具体),并且不能并行处理。

我认为TPL Dataflow可能是一个合适的解决方案。

这是我提出的过程:
阅读将由TransformBlock完成。接下来,我将创建对每个源的数据执行操作的类的实例。它们使用必要的参数进行初始化,以便他们知道如何处理文件的来源。 然后我会为每个创建的对象创建TransformBlocks(所以基本上为每个原点创建)。每个TransformBlocks将执行相应对象的功能。阅读文件的TransformBlock 会链接到BufferBlockTransformBlock会链接到每个{em>处理的每个TranformBlock linking would be conditional,以便只接收旨在到达原点处理ActionBlock的数据。处理块的输出将与maxDegreeOfParallelism链接以写入输出文件 每个Block都将input设置为1。

这是一个可行的解决方案吗?我想过用Tasks和BlockingCollection来实现它,但看起来这似乎是更简单的方法。

其他信息:

处理的文件数量可能会很大,要么一次加载。 读写应该与处理同时进行。由于I / O需要时间并且因为在处理形成输出文件之后需要收集数据,所以缓冲是必不可少的。

1 个答案:

答案 0 :(得分:1)

由于起源是独立的,并且每个起源的项目完全依赖,因此这个问题有一个简单的解决方案:

var origins = (from f in files
               group f by f.origin into g
               orderby g.Count() descending
               select g);

 var results =
 Partitioner.Create(origins) //disable chunking
 .AsParallel()
 .AsOrdered() //try process the biggest groups first
 .Select(originGroup => {
  foreach (var x in originGroup.OrderBy(...)) Process(x);
  return someResult;
 })
 .ToList();

按顺序处理每个原点并且并行处理。

如果您需要限制IO,则可以使用SemaphoreSlim来保护IO路径。