2013-10-10 23 views
-1

我有代碼看起來是這樣的:如何正確取消Parallel.Foreach?

Parallel.Foreach(ItemSource(),(item)=>DoSomething(item)); 

ItemSource()產生物品的無限流。

我希望一旦遇到一些條件就退出循環,而且我寧可在沒有在DoSomething中拋出異常的情況下執行它(我認爲這種方法是糟糕的編程風格)。

理想情況下,會有類似於cancellationToken的內容。我將在一個或多個線程中調用cancellationToken.Activate(),之後parallel.foreach將停止創建新線程,並且在最後一個線程退出後,該函數將返回。

這是可能在c#中使用Parallel.ForEach,或者我應該使用線程insteag?

UPDATE 以下是我microsoft suggests做到這一點:

 try 
     { 
      Parallel.ForEach(nums, po, (num) => 
      { 
       double d = Math.Sqrt(num); 
       Console.WriteLine("{0} on {1}", d, Thread.CurrentThread.ManagedThreadId); 
       po.CancellationToken.ThrowIfCancellationRequested(); 
      }); 
     } 
     catch (OperationCanceledException e) 
     { 
      Console.WriteLine(e.Message); 
     } 

我不喜歡這種做法,因爲它涉及到扔委託內部例外。

+0

看到更新...... –

+2

你不要一個選項不必拋出異常。您只需檢查CancellationToken.IsCancellationRequested屬性並以任何您想要的方式從該方法返回。 –

+4

拋出異常的好處是你有機會知道任務的調用者是否被取消。它在返回值的任務範圍中最有意義。例如,如果你運行一個任務來返回一個字符串......你怎麼知道是否有錯誤或取消?你可以返回null,但是如果null是這個任務的有效成功結果呢?例外情況在常規方法中與任務有相同的用處。 –

回答

4

在parallel.foreach有創造ParallelLoopState這種狀態下,您可以打破循環

ParallelOptions po = new ParallelOptions(); 
po.MaxDegreeOfParallelism = Constants.MaxParallelProcesses; 
var drc = Companies.AsEnumerable(); 

Parallel.ForEach(drc, po, (drcCompany, loopState) => 
{ 
    //do stuff here 
    if(YourBreakCondition) loopState.Break; 
} 

檢查這裏ParallelLoopState http://msdn.microsoft.com/es-es/library/system.threading.tasks.parallelloopstate.aspx

相關問題