Howto:Parallel.Foreach在每个进程运行一个新进程(但一次只有一个进程)后执行许多进程?

我相信有人知道这一点,我会非常感谢答案。 我不太了解代表和异步等等 – 所以请给我一个如何实现的一般例子。

我有一个工作流程,我可以使用Parallel.Foreach同时为许多不同的文件执行一个方法(甜,研磨处理器) – 但是在该方法结束后我需要运行另一个方法(它生成一个报告过程),这第二种方法不能并行运行。

我不想等待Parallel.ForEach中的所有文件在生成报告之前完成(这是不必要的)。 但是,如果我在第一个方法结束时启动报告生成方法,那么我会遇到问题。 是否有某种队列或什么? 必须有一些漂亮的方式,对吧?

谢谢

我认为Jim G的意思是:

var lockObj = new object(); Parallel.Foreach(files, file => { // Processing file lock(lockObj) { // Generate report. } }); 

第二种方法应该被链接为一个延续任务 。

在第二种方法中,使用lock或互斥锁以确保它不会并行运行。

并发和协调运行时(CCR)中的Arbiter.Interleave协调原语提供了一种实现所需function的简单方法。 基本上你传递3个接收器组1用于并发任务,1个用于独占任务(不是并行执行)和1个用于关闭整个过程。 您可以在此处找到如何使用它的示例

另一种选择是使用生产者 – 消费者模型。 您有一个线程安全阻塞集合 ,您将完成的数据放入其中,然后您有一个运行报告的线程从该集合中提取数据。

 //Collection to hold the data the processed files generated var proccesedDataItems = new new BlockingCollection(); //A thread that processes the files var processReports = new Task(() => { //Removes items from the collection, if the collection is empty it blocks // or if "CompletedAdded" has been called it will reach the "end" of the // collection foreach(var processedData in proccesedDataItems.GetConsumingEnumerable()) { BuildReport(processedData); } }); processReports.Start(); //Generating the data Parallel.Foreach(files, file => { var proccesedData = ProcessFile(file) proccesedDataItems.Add(processedData); }); //Let anyone consuming the collection that you can stop waiting for new items. proccesedDataItems.CompleteAdding(); 

这样的事情非常适合TPL Dataflow的模型:您创建一个处理文件的并行块,然后创建另一个生成报告的非并行块:

 var processFileBlock = new TransformBlock( file => ProcessFile(file), new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = DataflowBlockOptions.Unbounded }); var generateReportBlock = new ActionBlock( result => GenerateReport(result)); processFileBlock.LinkTo(generateReportBlock); foreach (var file in files) processFileBlock.Post(file); 

如果您还想等到所有处理完成,则需要使用Complete()Completetion添加一些代码。