[英]Task.WaitAll and Exceptions
我有異常處理和並行任務的問題。
下面顯示的代碼啟動2個任務並等待它們完成。 我的問題是,如果任務拋出異常,則永遠不會到達catch處理程序。
List<Task> tasks = new List<Task>();
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
}
但是,當我使用以下代碼等待超時的任務時,會捕獲異常。
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
確實等待所有任務完成,即使有些任務已經失敗。
以下是我解決問題的方法,正如我在回答/問題的評論中提到的那樣(上圖):
調用者捕獲由屏障協調的任務引發的任何異常,並通過強制取消發出其他任務的信號:
CancellationTokenSource cancelSignal = new CancellationTokenSource();
try
{
// do work
List<Task> workerTasks = new List<Task>();
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呼叫將顯示所有呼叫的最后一個帳號。 一旦我進入睡眠狀態,這個過程就很有效。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.