任务并行库-如何立即返回但有并行步骤 - c#

我具有以下需要以非阻塞并行处理方式进行的工作流程。我希望方法DoStuff()立即返回,所以我正在使用任务并行库

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);

参考方案

我认为您会感到困惑,因为您尝试将所有这些组件连接起来,作为原始事件的延续。如果没有令人信服的理由使所有这些调用都继续,则可以使用单个后台线程(任务)简单地完成所有操作。

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的方法返回值 - c#

我可能在这里错过了一些东西。语法不正确。static Task<int> MathOperation(int number) { //return new Task(new Func(TestMethod(number))); } static int LongRunningMethod(int number) { // some long ru…

任务工厂的每个循环等待 - c#

我是新手,对用法有疑问。 Task.Factory是否会在foreach循环中或在“等待”时阻塞所有项目,从而基本上使程序成为单线程?如果我正确地考虑了这个问题,则foreach循环将启动所有任务,然后执行.GetAwaiter()。GetResult();。正在阻塞主线程,直到最后一个任务完成。另外,我只是想要一些匿名任务来加载数据。这是正确的实施方式吗?…

并行编程:创建一定数量的过程和相关数据/工作 - c#

我需要根据用户PC逻辑核心的数量在不同的进程上分配工作负载。工作量由以下代码完成:static void work() { WorkData myData = new WorkData(); Worker myWorker = new Worker(myData); MyWorker.doWork() } 我用此代码计算逻辑核心:int nbProcesso…

LeetCode题解计算机为什么是基于二进制的?

可以是三进制么?二进制有什么好处?题解:为什么叫电子计算机?算盘应该没有二进制

LeetCode题解统计城市的所有灯泡

这个是我刚毕业的时候,一个真实的面试题,这是一个开放题。题目描述:想办法,将一个城市的所有灯泡数量统计出来。题解:费米估算法1、如果某个城市常驻人口有1000万2、假设每5人居住在一套房里,每套房有灯泡5只,那么住宅灯泡共有1000万只3、假设公众场所每10人共享一只灯泡,那么共有100万只4、主要的这两者相加就得出了1100万只当然实际上这是估算的,具体应…