Task.WaitAll和Exceptions

我有exception处理和并行任务的问题。

下面显示的代码启动2个任务并等待它们完成。 我的问题是,如果任务抛出exception,则永远不会到达catch处理程序。

List tasks = new List(); try { tasks.Add(Task.Factory.StartNew(TaskMethod1)); tasks.Add(Task.Factory.StartNew(TaskMethod2)); var arr = tasks.ToArray(); Task.WaitAll(arr); } catch (AggregateException e) { // do something } 

但是,当我使用以下代码等待超时的任务时,会捕获exception。

  while(!Task.WaitAll(arr,100)); 

我似乎错过了一些东西,因为WaitAll的文档描述了我的第一次尝试是正确的。 请帮助我理解它为什么不起作用。

无法重现这一点 – 它对我来说很好:

 using System; using System.Threading; using System.Threading.Tasks; class Test { static void Main() { Task t1 = Task.Factory.StartNew(() => Thread.Sleep(1000)); Task t2 = Task.Factory.StartNew(() => { Thread.Sleep(500); throw new Exception("Oops"); }); try { Task.WaitAll(t1, t2); Console.WriteLine("All done"); } catch (AggregateException) { Console.WriteLine("Something went wrong"); } } } 

就像我期望的那样,打印出“出了问题”。

您的某个任务可能没有完成吗? WaitAll确实等待所有任务完成,即使有些任务已经失败。

以下是我解决问题的方法,正如我对上述答案/问题的评论中提到的那样(上图):

调用者捕获由屏障协调的任务引发的任何exception,并通过强制取消发出其他任务的信号:

 CancellationTokenSource cancelSignal = new CancellationTokenSource(); try { // do work List workerTasks = new List(); foreach (Worker w in someArray) { workerTasks.Add(w.DoAsyncWork(cancelSignal.Token); } while (!Task.WaitAll(workerTasks.ToArray(), 100, cancelSignal.Token)) ; } catch (Exception) { cancelSignal.Cancel(); throw; } 

我试图为集合中的每个项目创建一个调用,结果是这样的:

 var parent = Task.Factory.StartNew(() => { foreach (var acct in AccountList) { var currAcctNo = acct.Number; Task.Factory.StartNew(() => { MyLocalList.AddRange(ProcessThisAccount(currAcctNo)); }, TaskCreationOptions.AttachedToParent); Thread.Sleep(50); } }); 

我必须在每次添加子任务后添加Thread.Sleep,因为如果我没有,那么该过程将倾向于在下一次迭代时覆盖currAcctNo。 我的列表中有3个或4个不同的帐号,当它们分别处理时,ProcessThisAccount呼叫将显示所有呼叫的最后一个帐号。 一旦我进入睡眠状态,这个过程效果很好。