如何确定所有任务何时完成

时间:2013-06-10 10:26:03

标签: c# task-parallel-library

这是启动多个任务的示例代码

Task.Factory.StartNew(() =>
        {
            //foreach (KeyValuePair<string, string> entry in dicList)

            Parallel.ForEach(dicList,
                entry =>
                {

                    //create and add the Progress in UI thread
                    var ucProgress = (Progress)fpPanel.Invoke(createProgress, entry);

                    //execute ucProgress.Process(); in non-UI thread in parallel. 
                    //the .Process(); must update UI by using *Invoke
                    ucProgress.Process();

                    System.Threading.Thread.SpinWait(5000000);
                });
        });
.ContinueWith(task => 
  {
      //to handle exceptions use task.Exception member

      var progressBar = (ProgressBar)task.AsyncState;
      if (!task.IsCancelled)
      {
          //hide progress bar here and reset pb.Value = 0
      }
  }, 
  TaskScheduler.FromCurrentSynchronizationContext() //update UI from UI thread
  );

当我们使用Task.Factory.StartNew()启动多个任务时,我们可以使用.ContinueWith()块来确定每个任务何时完成。我的意思是每次任务完成后,ContinueWith会阻止一次。所以我只想知道TPL库中是否有任何机制。如果我使用Task.Factory.StartNew()启动10个任务,那么在10个任务完成后如何通知我。请提供示例代码的一些见解。

4 个答案:

答案 0 :(得分:23)

  

如果我使用Task.Factory.StartNew()启动10个任务,那么如何在10个任务完成后通知

三个选项:

  • 阻止Task.WaitAll调用,仅在所有给定任务完成后才返回
  • 异步Task.WhenAll调用,它返回一个任务,该任务在所有给定任务完成时完成。 (在.NET 4.5中引入。)
  • TaskFactory.ContinueWhenAll,它添加了一个继续任务,该任务将在所有给定任务完成后运行。

答案 1 :(得分:2)

您可以使用WaitAll()。示例:

Func<bool> DummyMethod = () =>{
    // When ready, send back complete!
    return true;
};

// Create list of tasks
System.Threading.Tasks.Task<bool>[] tasks = new System.Threading.Tasks.Task<bool>[2];

// First task
var firstTask = System.Threading.Tasks.Task.Factory.StartNew(() => DummyMethod(), TaskCreationOptions.LongRunning);
tasks[0] = firstTask;

// Second task
var secondTask = System.Threading.Tasks.Task.Factory.StartNew(() => DummyMethod(), TaskCreationOptions.LongRunning);
tasks[1] = secondTask;

// Launch all
System.Threading.Tasks.Task.WaitAll(tasks);

答案 2 :(得分:2)

  

如果我使用Task.Factory.StartNew()启动10个任务,那么如何在10个任务完成后通知

您可以使用Task.WaitAll。此调用将阻止当前线程,直到所有任务完成。

旁注:您似乎正在使用TaskParallelThread.SpinWait,这会使您的代码变得复杂。我会花一点时间分析是否真的有必要进行复杂化。

答案 3 :(得分:0)

另一种解决方案:

完成Parallel.For(...)内部的所有操作后,它返回ParallelLoopResultDocumentation的对象:

  

For在以下情况下返回 System.Threading.Tasks.ParallelLoopResult 对象   所有线程均已完成。当您处于以下状态时,此返回值很有用   手动停止或中断循环迭代,因为    ParallelLoopResult 存储诸如上一次迭代之类的信息   跑完了。如果其中一个发生一个或多个例外   线程,将抛出 System.AggregateException

ParallelLoopResult类具有IsCompleted属性,当执行Stop()方法中的Break()时,该属性设置为false。

示例:

ParallelLoopResult result = Parallel.For(...);

if (result.IsCompleted)
{
    //Start another task
}

请注意,建议仅在手动中断或停止循环时使用它(否则,只需使用WaitAllWhenAll等)。