2011-10-24 14 views

回答

128

如果您創建一個任務,你永遠不要叫task.Wait()或嘗試檢索Task<T>的結果,當垃圾收集器收集任務時,它將在最終確定期間拆除您的應用程序。有關詳細信息,請參閱MSDN的頁面Exception Handling in the TPL

這裏最好的選擇是「處理」異常。這可以通過延續完成 - 您可以將延續附加到任務,並記錄/吞下/等發生的異常。這提供了一個乾淨的方式來登錄任務異常,並可以寫成一個簡單的擴展方法,即:

public static void LogExceptions(this Task task) 
{ 
    task.ContinueWith(t => 
    { 
     var aggException = t.Exception.Flatten(); 
     foreach(var exception in aggException.InnerExceptions) 
      LogException(exception); 
    }, 
    TaskContinuationOptions.OnlyOnFaulted); 
} 

通過上述,您可以防止拆除的應用程序,並記錄它,通過任何任務:

Task.Factory.StartNew(() => 
    { 
     // Do your work... 
    }).LogExceptions(); 

或者,您可以訂閱TaskScheduler.UnobservedTaskException和處理它。

+14

對於增加了娛樂功能,在一個名爲你選擇的四個字母的單詞的類中有一個靜態存根方法'Off',並將它用於你的全部延續。有助於打擊來自這個特殊例外的一些被壓抑的挫敗感。 – Aaronaught

+0

實際上,這發生在我稱爲tpl任務內部的公共靜態函數的地方。使用try catch會解決這個問題?我真的需要創建另一個任務並等待它嗎? – MonsterMMORPG

+0

@MonsterMMORPG:捕獲異常的函數(公共靜態)中的try catch會處理它。問題是一個例外是「冒泡」到任務本身,並且你從不等待任務完成。如果你這樣做,它會解決它。 –

32

當然;這意味着一個Task被留在垃圾回收後被終結,但任務本身失敗。有兩種解決方法:

  • 處理任務失敗直接(使用ContinueWith(...)認購,並在參數檢查.IsFaulted.ExceptionTask
  • 處理TaskScheduler.UnobservedTaskException事件,並將其標記觀察(調用e.SetObserved()後記錄錯誤)
+3

+1 - 有一個補充 - 如果你的延續除了檢查'IsFaulted'外什麼都沒做,你可以使用'OnlyOnFaulted'延續選項並避免手動檢查... –

+0

實際上這發生在我調用內部公共靜態函數的地方的tpl任務。使用try catch會解決這個問題?我真的需要創建另一個任務並等待它嗎?感謝 – MonsterMMORPG

+3

+1,因爲需要調用'UnobservedTaskExceptionEventArgs'上的'SetObserved'。 –

-13

試試這個:

public static void ThrowFirstExceptionIfHappens(this Task task) 
{ 
    task.ContinueWith(t => 
    { 
     var aggException = t.Exception.Flatten(); 
     foreach (var exception in aggException.InnerExceptions) 
     { 
      throw exception; // throw only first, search for solution 
     } 
    }, 
    TaskContinuationOptions.OnlyOnFaulted); // not valid for multi task continuations 
} 

public static Task CreateHandledTask(Action action) 
{ 
    Task tsk = Task.Factory.StartNew(action); 
    tsk.ThrowFirstExceptionIfHappens(); 
    return tsk; 
} 
+5

_Its one _ ???你什麼意思?你能解釋一下你的答案對答案的貢獻嗎? –

+0

你剛剛通過繼續創建了一個新任務,然後失敗並進入相同的狀態。 –