任务并行库 - 如何立即返回,但有一个平行台阶(Task Parallel Library - ho

2019-09-16 13:40发布

我有以下的工作流程需要在一个非阻塞并行处理的方式发生。 我想方法DoStuff()来立刻让我使用任务并行Libary返回

DoStuff():
  Do some setup
  Parse an Excel file

  then for each row
   Fill Template with parsed values
   Convert filled template to Pdf
   Convert pdf to Tiff

  when all row processing has completed Create Summary Text File

  when summary text file has completed, Finalize

我绊了一下与“当所有行的处理已完成”的步骤,因为我想立即返回。 在下面的大概是我应该做的?

public Task<ProcessingResult> DoStuff() {
    return new Task<SetupResult>(SetUp)
        .ContinueWith(ParseExcel, TaskContinuationOptions.OnlyOnRanToCompletion)
        .ContinueWith(excelProcessing => {
            var templateProcessing = excelProcessing.Result.RowParsing
                .Select(template =>
                  new Task<TemplateFillingResult>(()=>FillTemplate)
                       .ContinueWith(ConvertToPdf, TaskContinuationOptions.OnlyOnRanToCompletion)
                       .ContinueWith(ConvertToTiff, TaskContinuationOptions.OnlyOnRanToCompletion)
                ).ToArray()

            //-------------------------------------------------------------
            // This is the part that seems wierd
            //-------------------------------------------------------------
            Task.Factory.ContinueWhenAll(templateTasks, t=> { }).Wait();
            return new TemplatesProcessingResult(templateProcessing);
        }, TaskContinuationOptions.OnlyOnRanToCompletion)
        .ContinueWith(CreateSummaryFile, TaskContinuationOptions.OnlyOnRanToCompletion)
        .ContinueWith(FinalizeProcessing, TaskContinuationOptions.OnlyOnRanToCompletion);

Answer 1:

我想你感到困惑,因为你正试图连线了所有这些组件的原始事件的延续。 如果没有令人信服的理由,使所有这些调用延续的,那么这都可以简单地用一个后台线程(任务)完成的。

var task = Task.Factory.StartNew(() =>
   {
        // setup
        // var stuff = ParseFile()

        // Executes elements in parallel and blocks this thread until all have completed, else bubbles the exception up
        var transformations = excelProcessing.Result.RowParsing.AsParallel().Select(x =>
           {
                FillTemplate(x);
           }).ToArray();

        // create summary text file

        // Finalize

        return processingResult;
   });

基本上,你可以做所有的,在一个单独的线程,而不必担心。 标记了所有这些步骤的延续是你需要做的相当令人费解。

然后调用代码可以直接在程序Result那家伙的属性来获取异步调用的结果:

  try
  {
      var result = task.Result;
  }
  catch(AggregateException e)
  {
      e.Flatten().Handle(ex => 
        {
             // Do Stuff, return true to indicate handled
        });
  }

然而,有一件事你需要认识到的是例外。 如果这将是一个射后不理的任务,那么,如果你有一个例外,这将泡一路攀升,并可能杀死你的进程。



文章来源: Task Parallel Library - how to return immediately but have a parallel step