0

這實際上是我自己的響應我的回答Circular dependency with cross-cutting concern任何方式來保證所有任務將嘗試與任務並行庫?

一個問題是存在的Parallel.ForEach變體,至少保證每一個可能的任務將至少試圖不論是否有特定的任務拋出一個異常?

我知道我可以在包裝每個任務它自己的try/catch/finally等,(直接或間接),並可能使用一些同步容器保存異常,或什麼的,但好像很多與工作的 - 有許多可能的解決方案來評估 - 我認爲Task Parallel可以更好地處理任務並行庫。

我在任務中拋出異常的嘗試似乎暗示Parallel.ForEach可能會中止並取消任何剩餘的任務)。 {some enumerable}.AsParallel().ForAll({the task});的情況似乎相似。我認爲在某些情況下,放棄剩餘任務的策略 - 或者在創建剩餘任務之前放棄 - 這可能是 - 是完全可以接受的行爲。然而,有時候,任務將會死於,我們最好嘗試儘可能多地運行任務,並跟蹤哪些存活以及哪些死亡。

我所以看到How to handle all unhandled exceptions when using Task Parallel Library?,但它不清楚,如果這答案我的問題。

http://blogs.msdn.com/b/pfxteam/archive/2009/05/31/9674669.aspx < =也可能是相關的。

對於我來說,這不是一個高度重要的問題,我只是認爲我會把它扔出去,以防其他人想要提供答案。

編輯:爲防萬一代碼中存在一個錯誤來演示行爲,這裏是(也與其他問題有關)。我一直在LinqPad上運行它,有時我會看到所有的結果,有時候我不會。請不要批評代碼質量,我只想看看我是否明白髮生了什麼。我懷疑可能有一些與[ThreadStatic]修改過的變量有關。

static void Main() //Main(string[] args) 
{ 
    string[] messages = "this is a test. but it's going to be an issue!".Split(' '); 

    try{ 
     messages.AsParallel().ForAll(Log); 
    } catch(AggregateException){ 
     throw; 
    } 

    Console.ReadLine(); 
} 
[ThreadStatic] 
static bool _disable = false; 
public static void Log(string message) 
{ 
    if (_disable) 
    { 
     return; 
    } 
    try { 
     _disable = true; 
     Console.WriteLine(GetPrefix() + message); 
     throw new Exception("bar"); 
    } finally { 
     _disable = false; 
    } 
} 

public static string GetPrefix() 
{ 
    Log("Getting prefix!"); 
    return "Prefix: "; 
} 

回答

1

首先,我認爲當你談論任務時會感到困惑。你有什麼是循環的迭代,將使用Task並行執行,但這並不意味着每次迭代都是一項任務。其次,如果你真的只是爲了記錄而做這件事,你不可能獲得任何性能增益,我不認爲日誌是可並行化的。

現在,您可以做的是手動爲每個循環迭代創建一個單獨的Task,然後等待它們使用Task.WaitAll()完成。這樣,所有迭代都會執行,如果其中一些失敗,WaitAll()將拋出一個包含它們的AggregateException

var tasks = messages.Select(m => Task.Factory.StartNew(() => Log(m))); 
Task.WaitAll(tasks.ToArray()); 

這很可能將是效率較低是Parallel.ForEach()或PLINQ,但可能你會好起來。如果沒有,那麼您必須使用您建議的方法try - catch

+0

首先,我想這種混亂似乎是我的問題的來源。其次,*雖然這種使用任務進行日誌記錄也困擾我*,但日誌記錄僅與http://stackoverflow.com/questions/17729907/circular-dependency-with-cross-cutting-concern/中提到的奇怪需求有關17731370#17731370。 – JayC

+0

這個'Task.WaitAll'確實似乎是我的問題的答案,但我想知道,如果每個操作被賦予一個單獨的任務而不是Parrallel.ForEach(xxx,action)的工作負載,Task.WaitAll的工作負載有多不同, '或者'xxx.AsParallel().ForAll(action)',這些行爲顯然是在任務之間分配的。 – JayC

+0

@JayC你不必懷疑。用兩種方式編寫真實代碼,然後測量差異。 – svick