C#Task.WaitAll()取消错误处理

问题描述:

我有一个问题。 我尝试运行多个长时间运行的任务。如果一个失败,我想取消所有其他任务并获得失败例外。 下面给出的例子。与异常 我想捕捉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

这对我的作品

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

您应该投掷AggregateException构造函数,而不是仅仅Exception使用:

throw new AggregateException ("FailureTask");