3

我相信有人知道这一点,我将非常感谢您的回答。我对委托和异步等知之甚少 - 所以请给我一个如何实现的一般示例。

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

我不想在生成报告之前等待 Parallel.ForEach 中的所有文件完成(这不是必需的)。但是,如果我在第一个方法结束时开始报告生成方法,那么我就会遇到问题。有什么排队之类的吗?一定有一些漂亮的方法,对吧?

谢谢

4

5 回答 5

2

我认为 Jim G 的意思是:

var lockObj = new object();

Parallel.Foreach(files, file => 
{
    // Processing file
    lock(lockObj)
    {
        // Generate report.
    }
});
于 2012-09-07T19:17:31.670 回答
1

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

在第二种方法中,使用 alock或 mutex 以确保它不会并行运行。

于 2012-09-07T19:05:29.453 回答
1

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

于 2012-09-07T19:26:14.527 回答
1

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

//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();
于 2012-09-07T19:54:39.987 回答
1

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

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()and添加一些代码Completetion

于 2012-09-08T00:07:12.427 回答