2014-03-28 38 views
0

我想改進以下代碼以添加取消支持。基本上,我需要做的是一旦孩子拋出異常,取消所有孩子以及父任務。我寫了下面的代碼作爲學習經驗。只有孩子們完成後,我才能看到AggregateException,但我不想那樣。當其中一個引發異常時取消子任務

static int GetSum() 
    { 
     var parent = Task<int>.Factory.StartNew(() => 
     { 
      var children = new Task<int>[100]; 
      for (var i = 0; i < children.Length; i++) 
      { 
       var index = i; 
       children[index] = Task<int>.Factory.StartNew(() => 
       { 
        var randomNumber = new Random().Next(5); 
        if (randomNumber == 0) 
        { 
         throw new Exception(); 
        } 

        return randomNumber; 
       }, TaskCreationOptions.AttachedToParent); 
      } 

      Task.WaitAll(); 
      Console.WriteLine("Children finished"); 
      return children.Sum(t => t.Result); 
     }); 

     parent.Wait(); 
     Console.WriteLine("Parent finished"); 
     return parent.Result; 
    } 

我相信我需要使用下面的,雖然我不知道如何:

var source = new CancellationTokenSource(); 
var token = source.Token; 
+0

你已經採取了看看http://msdn.microsoft.com/en-us/library/dd537607(v=vs.110).aspx –

回答

2

你可以使用Task.WaitAny,而不是爲WaitAll,並作出取消請求令牌一旦AgregateException是拋出這樣的事情

static int GetSum() 
    { 
     var tokenSource = new CancellationTokenSource(); 
     var token = tokenSource.Token; 
     var parent = Task<int>.Factory.StartNew(() => 
     { 
      var children = new Task<int>[100]; 
      for (var i = 0; i < children.Length; i++) 
      { 
       var index = i; 
       children[index] = Task<int>.Factory.StartNew(() => 
       { 
        for (int j = 0; j < 100000; j++) 
        { 


        if (!token.IsCancellationRequested) 
        { 


         var randomNumber = new Random().Next(5); 
         if (randomNumber == 0) 
         { 
          throw new Exception(); 
         } 

         return randomNumber; 
        } 
        else 
        { 
         token.ThrowIfCancellationRequested(); 
        } 
        } 
        return 0; 
       } 
       , token); 
      } 
      try 
      { 
       Task.WaitAny(children); 
      } 
      catch (AggregateException ae) 
      { 
       tokenSource.Cancel(); 
       ae.Handle((task) => 
        { 
         Console.WriteLine("Cancel all others child tasks requested "); 
         return true; 
        }); 
      } 

      Console.WriteLine("Children finished"); 
      return children.Sum(t => t.Result); 
     }); 

     try 
     { 
      parent.Wait(); 
     } 
     catch (AggregateException aex) 
     { 
      aex.Handle((task) => 
      { 
       Console.WriteLine("Cancel child work done "); 
       return true; 
      });    
     } 

     Console.WriteLine("Parent finished"); 
     return parent.Result; 
    } 
+0

感謝。這是一個很好的例子。我對ThrowIfCancellationRequested的理解是代碼執行需要達到此方法調用,以便我們殺死一個子任務。如果在執行期間在其前面的if塊內執行取消操作,則該塊仍需完成。 – Mark13426

相關問題