1

我有一個問題。 我嘗試運行多個長時間運行的任務。如果一個失敗,我想取消所有其他任務並獲得失敗例外。 下面給出的例子。與異常 我想捕捉AggregateException通過C#Task.WaitAll()取消錯誤處理

throw new Exception("FailureTask"); 

拋出但不是AggregateException我趕上OperationCanceledException,因爲我想取消所有其他任務。

[TestMethod] 
    public void TestParallelTaskCancelation() 
    { 
     var cancellationTokenSource = new CancellationTokenSource(); 
     Task[] tasks = 
     { 
      Task.Factory.StartNew(DummyTask, cancellationTokenSource, cancellationTokenSource.Token), 
      Task.Factory.StartNew(DummyTask, cancellationTokenSource, cancellationTokenSource.Token), 
      Task.Factory.StartNew(DummyTask, cancellationTokenSource, cancellationTokenSource.Token), 
      Task.Factory.StartNew(DummyTask, cancellationTokenSource, cancellationTokenSource.Token), 
      Task.Factory.StartNew(FailureTask, cancellationTokenSource, cancellationTokenSource.Token) 
     }; 

     try 
     { 
      Task.WaitAll(tasks, cancellationTokenSource.Token); 
     } 
     catch (OperationCanceledException e) 
     { 
      Console.WriteLine(e.GetaAllMessages()); 
     } 
     catch (AggregateException e) 
     { 
      Console.WriteLine(e.GetaAllMessages()); 
     } 
    } 

    private void DummyTask(object o) 
    { 
     var cancellationToken = (CancellationTokenSource)o; 
     while (true) 
     { 
      Thread.Sleep(10000); 
      if (cancellationToken.IsCancellationRequested) 
      { 
       cancellationToken.Token.ThrowIfCancellationRequested(); 
      } 
     } 
    } 

    private void FailureTask(object o) 
    { 
     var cancellationToken = (CancellationTokenSource)o; 

     var executionTask = Task.Factory.StartNew(() => 
     { 
      Thread.Sleep(1000); 
      throw new Exception("FailureTask"); 
     }, cancellationToken.Token); 

     executionTask.ContinueWith(t => 
     { 
      cancellationToken.Cancel(false); 
      throw new Exception(t.Exception.GetaAllMessages()); 
     }, TaskContinuationOptions.OnlyOnFaulted); 

     if (executionTask.Wait(10 * 1000, cancellationToken.Token)) return; 
     //timeout !!! 
     throw new Exception("The limit 'Max Seconds Per Query' has been exceeded!!!"); 
    }` 

請幫忙。

+0

你拋出一個'Exception'這是所有異常的基類。 'OperationCanceledException'和'AggregateException'派生自'Exception'。你的例外永遠不會被捕獲,因爲你只是捕獲更具體的例外。要捕獲一個'AggregateException',你必須拋出一個'AggregateException'。 –

+0

如果兩個或更多任務同時失敗,該怎麼辦?那麼我會抓住哪個例外?我所理解的是,AggregateException應該包括已取消任務的取消異常和其他任務的異常。 – Gintaras

+0

拋出新的AggregateException(「FailureTask」);沒有工作。即使僅捕獲(基本)異常捕獲OperationCanceledException。 – Gintaras

回答

2

這對我的作品

public static async void TestParallelTaskCancelation() 
    { 
     var cancellationTokenSource = new CancellationTokenSource(); 
     Task[] tasks = 
     { 
     Task.Factory.StartNew(DummyTask, cancellationTokenSource, cancellationTokenSource.Token), 
     Task.Factory.StartNew(DummyTask, cancellationTokenSource, cancellationTokenSource.Token), 
     Task.Factory.StartNew(DummyTask, cancellationTokenSource, cancellationTokenSource.Token), 
     Task.Factory.StartNew(DummyTask, cancellationTokenSource, cancellationTokenSource.Token), 
     Task.Factory.StartNew(FailureTask, cancellationTokenSource, cancellationTokenSource.Token) 
     }; 

     try 
     { 
      await Task.WhenAll(tasks); 
     } 
     catch (OperationCanceledException e) 
     { 
      Console.WriteLine(e.ToString()); 
     } 
     catch (AggregateException e) 
     { 
      Console.WriteLine(e.ToString()); 
     } 
    } 
+1

這是正確的答案:-)你比我快......你不必取消等待,因爲你想等到所有其他線程都被取消爲止 – ascholz

+0

不,如果失敗了,我需要取消所有其他線程。 – Gintaras

+0

當FailureTask失敗時,所有其他人將被cancellationToken取消 – Ive

1

您應該投擲AggregateException構造函數,而不是僅僅Exception使用:

throw new AggregateException ("FailureTask");