簡體   English   中英

Task.WaitAll和Exceptions

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM