我想知道以下方法是否是在C#.NET 4.6.1中实现生产者和消费者模式的好方法
我想做什么的说明:
我想读取文件,对数据进行计算并保存结果。每个文件都有一个源(一个设备,例如数据记录器),根据该来源,应该使用不同的计算和输出格式。该文件包含不同的值,例如几个传感器的温度读数。计算具有状态是很重要的。例如,这可能是先前计算的最后一个值,例如,如果我想总结一个原点的所有值。
我想并行处理每个来源的处理。一个来源的所有文件需要按顺序处理(或按时间顺序更具体),并且不能并行处理。
我认为TPL Dataflow可能是一个合适的解决方案。
这是我提出的过程:
阅读将由TransformBlock
完成。接下来,我将创建对每个源的数据执行操作的类的实例。它们使用必要的参数进行初始化,以便他们知道如何处理文件的来源。
然后我会为每个创建的对象创建TransformBlocks
(所以基本上为每个原点创建)。每个TransformBlocks
将执行相应对象的功能。阅读文件的TransformBlock
会链接到BufferBlock
,TransformBlock
会链接到每个{em>处理的每个TranformBlock
。 linking would be conditional,以便只接收旨在到达原点处理ActionBlock
的数据。处理块的输出将与maxDegreeOfParallelism
链接以写入输出文件
每个Block都将input
设置为1。
这是一个可行的解决方案吗?我想过用Tasks和BlockingCollection来实现它,但看起来这似乎是更简单的方法。
其他信息:
处理的文件数量可能会很大,要么一次加载。 读写应该与处理同时进行。由于I / O需要时间并且因为在处理形成输出文件之后需要收集数据,所以缓冲是必不可少的。
答案 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路径。