【问题标题】:Task chaining (wait for the previous task to completed)任务链(等待上一个任务完成)
【发布时间】:2012-07-23 21:05:11
【问题描述】:
var tasks = new List<Task>();

foreach (var guid in guids)
{
    var task = new Task( ...);
    tasks.Add(task);
}

foreach (var task in tasks)
{
    task.Start();
    Task.WaitAll(task);
}

这是 UI 线程的运行。我需要一个接一个地执行任务变量中的所有任务。问题是如果我调用 Task.WaitAll(task),UI 会冻结。如何在不冻结 UI 的情况下执行以下逻辑?

【问题讨论】:

  • 那你为什么不做一个大代表呢?
  • 补充@SLaks 所说的,如果你只有一个要运行的东西的列表,使用像BackgroundWorker 这样的东西可能会更简单。真正的未知数是您希望在后台工作完成后发生什么 - 假设它是某种 UI 更新,BackgroundWorker 已经通过在 UI 线程上运行已完成的委托来为您处理。

标签: c# .net task-parallel-library task


【解决方案1】:

你需要使用延续:

lastTask.ContinueWith(() => newTask.Start());

【讨论】:

    【解决方案2】:

    这不是任务链。

    您需要使用ContinueWith 进行任务链接。最后一个任务需要更新 UI。

    Task.Factory.StartNew( () => DoThis())
       .ContinueWith((t1) => DoThat())
       .ContinueWith((t2) => UpdateUi(), 
           TaskScheduler.FromCurrentSynchronizationContext());
    

    注意最后一行有TaskScheduler.FromCurrentSynchronizationContext() 这将确保任务将在同步上下文(UI 线程)中运行。

    【讨论】:

      【解决方案3】:

      最好的方法是使用Task Parallel Library (TPL)Continuations。延续不仅允许您创建任务流,还可以处理您的异常。这是 TPL 的great introduction。但是给你一些想法......

      您可以使用

      启动 TPL 任务
      Task task = Task.Factory.StartNew(() => 
      {
          // Do some work here...
      });
      

      现在要在前面的任务完成(错误或成功)时启动第二个任务,您可以使用ContinueWith 方法

      Task task1 = Task.Factory.StartNew(() => Console.WriteLine("Antecedant Task"));
      Task task2 = task1.ContinueWith(antTask => Console.WriteLine("Continuation..."));
      

      所以只要task1 完成、失败或被取消task2 'fires-up' 并开始运行。请注意,如果task1 在到达第二行代码之前完成,task2 将被安排立即执行。传递给第二个 lambda 的 antTask 参数是对前面任务的引用。有关更多详细示例,请参阅this link...

      您还可以传递先前任务的延续结果

      Task.Factory.StartNew<int>(() => 1)
          .ContinueWith(antTask => antTask.Result * 4)
          .ContinueWith(antTask => antTask.Result * 4)
          .ContinueWith(antTask =>Console.WriteLine(antTask.Result * 4)); // Prints 64.
      

      注意。请务必阅读提供的第一个链接中的异常处理,因为这可能会使新手误入 TPL。

      最后一件需要特别注意的是子任务。子任务是那些创建为AttachedToParent 的任务。在这种情况下,直到所有子任务都完成后,延续才会运行

      TaskCreationOptions atp = TaskCreationOptions.AttachedToParent;
      Task.Factory.StartNew(() =>
      {
          Task.Factory.StartNew(() => { SomeMethod() }, atp);
          Task.Factory.StartNew(() => { SomeOtherMethod() }, atp); 
      }).ContinueWith( cont => { Console.WriteLine("Finished!") });
      

      我希望这会有所帮助。

      【讨论】:

        猜你喜欢
        • 2015-08-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-02-24
        • 2020-05-19
        相关资源
        最近更新 更多