10

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

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()当我们使用then启动多个任务时,我们可以使用.ContinueWith()block 来确定每个任务何时完成。我的意思是每个任务完成时,ContinueWith 块触发一次。所以我只想知道 TPL 库中是否有任何机制。如果我开始使用 10 个任务,Task.Factory.StartNew()那么我如何在 10 个任务完成后通知。请通过示例代码提供一些见解。

4

4 回答 4

25

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

三个选项:

  • 阻塞Task.WaitAll调用,仅在所有给定任务完成时返回
  • 异步Task.WhenAll调用,它返回一个在所有给定任务完成后完成的任务。(在 .NET 4.5 中引入。)
  • TaskFactory.ContinueWhenAll,它添加了一个延续任务,该任务将在所有给定任务完成后运行。
于 2013-06-10T10:29:47.187 回答
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);
于 2013-06-10T10:30:17.163 回答
2

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

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

旁注:您似乎正在使用Task,ParallelThread.SpinWait,这使您的代码变得复杂。我会花一些时间来分析这种复杂性是否真的有必要。

于 2013-06-10T10:30:49.710 回答
1

另一种解决方案:

完成里面的所有操作后Parallel.For(...),返回一个 onject ParallelLoopResult文档

For在所有线程都完成后返回一个System.Threading.Tasks.ParallelLoopResult对象。当您手动停止或中断循环迭代时,此返回值很有用,因为 ParallelLoopResult存储信息,例如运行到完成的最后一次迭代。如果其中一个线程发生一个或多个异常,则会抛出System.AggregateException

该类ParallelLoopResult有一个属性,当执行了of方法时,该IsCompleted属性设置为 false 。Stop()Break()

例子:

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

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

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

于 2018-10-03T19:25:19.607 回答