我相信有人知道这一点,我会非常感谢答案。我对代表和异步等都不太了解 - 所以请给我一个如何实现的一般例子。
我有一个工作流程 我可以使用Parallel.Foreach同时为许多不同的文件执行一个方法(甜,研磨处理器) - 但是在该方法结束后我需要运行另一个方法(它生成一个关于前一个过程的报告), 并且第二种方法不能并行运行。
我不想等到Parallel.ForEach中的所有文件在生成报告之前完成(这是不必要的)。但是如果我在第一种方法结束时启动报告生成方法,那么我会遇到问题。有某种队列或什么?有一些很好的方法,对吧?
由于
答案 0 :(得分:2)
我认为Jim G的意思是:
var lockObj = new object();
Parallel.Foreach(files, file =>
{
// Processing file
lock(lockObj)
{
// Generate report.
}
});
答案 1 :(得分:1)
第二种方法应链接为continuation task。
在第二种方法中,使用lock
或互斥锁以确保它不会并行运行。
答案 2 :(得分:1)
并发和协调运行时(CCR)中的Arbiter.Interleave协调原语提供了一种实现所需功能的简单方法。基本上你传递3个接收器组1用于并发任务,1个用于独占任务(不是并行执行)和1个用于关闭整个过程。您可以找到如何使用它的示例here
答案 3 :(得分:1)
另一种选择是使用生产者 - 消费者模型。您有一个thread safe blocking collection,您将完成的数据放入其中,然后您有一个运行报告的线程从该集合中提取数据。
//Collection to hold the data the processed files generated
var proccesedDataItems = new new BlockingCollection<ResultData>();
//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();
答案 4 :(得分:1)
这样的事情非常适合TPL Dataflow的模型:您创建一个处理文件的并行块,然后创建另一个生成报告的非并行块:
var processFileBlock = new TransformBlock<File, Result>(
file => ProcessFile(file),
new ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism = DataflowBlockOptions.Unbounded
});
var generateReportBlock = new ActionBlock<Result>(
result => GenerateReport(result));
processFileBlock.LinkTo(generateReportBlock);
foreach (var file in files)
processFileBlock.Post(file);
如果您还想等到所有处理完成,则需要使用Complete()
和Completetion
添加一些代码。