11

觀察任務內拋出的異常有多種方式。其中之一是與OnlyOnFaulted一個ContinueWith:在ContinueWith中觀察任務異常

var task = Task.Factory.StartNew(() => 
{ 
    // Throws an exception 
    // (possibly from within another task spawned from within this task) 
}); 

var failureTask = task.ContinueWith((t) => 
{ 
    // Flatten and loop (since there could have been multiple tasks) 
    foreach (var ex in t.Exception.Flatten().InnerExceptions) 
     Console.WriteLine(ex.Message); 
}, TaskContinuationOptions.OnlyOnFaulted); 

我的問題:你的例外自動成爲一次failureTask開始觀察到的,還是他們只能成爲觀測一次我「觸摸」 ex.Message?

+1

你是什麼意思的觀察?您的ContinueWith委託只會被調用一次,如果這就是您的意思,無論您是否訪問該異常對象。 – 2012-07-31 15:40:37

+0

也許他的意思是「如果我簡單地調用'OnlyOnFaulted'而不管訪問't.Exceptions'」是否會重新拋出異常? – user7116 2012-07-31 15:45:25

+0

如果您不「觀察」任務引發的異常(這是Microsoft術語),那麼垃圾收集器將在稍後爲您拋出它們。我的ContinueWith委託肯定會被多次調用(如果在我的主任務中有多個任務會拋出異常),或者它可以用帶有所有拋出的異常的AggregateException樹調用? – davenewza 2012-07-31 15:47:18

回答

10

他們被視爲觀察到一旦您訪問Exception屬性。請參閱AggregateException.Handle。您可以使用t.Exception.Handle代替:

t.Exception.Handle(exception => 
      { 
      Console.WriteLine(exception); 
      return true; 
      } 
    ); 
+0

謝謝。似乎有很多方法來處理任務異常。 – davenewza 2012-07-31 16:04:24

+1

是的,我更喜歡Handle方法;因爲它更加明確。但是,在任何情況下都可能無法使用。 – 2012-07-31 16:07:25

2

樣品

Task.Factory.StartNew(testMethod).ContinueWith(p => 
      { 
       if (p.Exception != null) 
        p.Exception.Handle(x => 
         { 
          Console.WriteLine(x.Message); 
          return false; 
         }); 
      }); 
+2

如果要將異常標記爲已處理(如上面的回答),那麼傳遞給Handle()函數的謂詞不應該返回true嗎?我想這取決於你想要做什麼,但我在這裏假設我們要將異常標記爲已處理。 – 2013-09-25 22:05:38