2011-08-18 172 views
5

當使用Task.WaitAll等待任務並指定超時(如果WaitAll超時)時,我還必須單獨觀察任何未完成的任務(例如,通過註冊延續)?任務和Task.WaitAll具有超時異常處理

This thread讓我覺得答案是肯定的,但我還沒有發現任何證實這一點的東西。

var random = new Random(); 
var tasks = Enumerable.Range(0, 10).Select((i) => Task.Factory.StartNew(() => { 
     // Sleep 5-15 seconds 
     Thread.Sleep(random.Next(5000, 15000)); 
     throw new Exception("Some exception."); 
    } 
)).ToArray(); 

try { 
    // Wait for 10 seconds 
    Task.WaitAll(tasks, 10000); 
} catch (AggregateException) { 
    // Swallow 
} 

// Check to see how many tasks were unfinished 
tasks.Where(t => !t.IsCompleted).Count().Dump("Unfinished count: "); 

// Is this neccessary to avoid exceptions being thrown on the finalizer? 
foreach (Task task in tasks) { 
    task.ContinueWith(t => t.Exception, TaskContinuationOptions.OnlyOnFaulted); 
} 
+0

在WaitAll後捕獲的AggregateException中存在多少個異常? –

+0

完整的簡單lib源代碼在這裏:http://stackoverflow.com/questions/11831844/unobservedtaskexception-being-throw-but-it-is-handled-by-a-taskscheduler-unobser – 2013-01-21 15:30:42

回答

0

測試與LINQPad V4.31表明答案是肯定的,因爲如果你註釋掉的foreach你得到每個未完成的任務未處理的異常對話框。

我相信我明白爲什麼這是在這一點上,但如果有人想要在這個行爲的更多技術性的解釋去一切去爲它。

2

爲避免碰撞終結器,您必須觀察Task主體拋出的異常。觀察一個Task例外,你必須做下列之一:

  1. 訪問異常財產
  2. 呼叫Task.Wait/WaitAll/WaitAny
  3. 註冊的延續,只有當任務故障
運行

你所做的事絕對有必要避免碰撞終結者。