2013-04-16 61 views
5

取消操作與loopState操作(Break/Stop)之間有什麼區別?parallel.foreach - loopState.Stop()與取消

private static CancellationTokenSource cts; 
public static loopingMethod() 
{ 
cts = new CancellationTokenSource(); 
try 
{ 
    ParallelOptions pOptions = new ParallelOptions(); 
    pOptions.MaxDegreeOfParallelism = 4; 
    pOptions.CancellationToken = cts.Token; 
    Parallel.ForEach(dictObj, pOptions, (KVP, loopState) => 
    { 
     pOptions.CancellationToken.ThrowIfCancellationRequested(); 
     parallelDoWork(KVP.Key, KVP.Value, loopState); 
    }); //End of Parallel.ForEach loop 
} 
catch (OperationCanceledException e) 
{ 
//Catestrophic Failure 
return -99; 
} 
} 

public static void parallelDoWork(string Id, string Value, ParallelLoopState loopState) 
{ 
    try{ 
     throw new exception("kill loop"); 
    } 
    catch(exception ex) 
    { 
     if(ex.message == "kill loop") 
     { 
      cts.Cancel(); 
      //Or do I use loopState here? 
     } 
    } 
} 

我爲什麼要使用ParallelOptions取消操作相對於loopState.Break();loopState.Stop();或反之亦然?

回答

2

看到這個article

「設置取消標記允許您中止調用(請記住,當一個委託拋出一個異常,異常吞嚥並只調用畢竟其他代表已經重新拋出執行)「。

場景1.想象一下,你有一個用戶即將消息發送給所有前女友|朋友。他們點擊發送,然後他們意識到並想取消它。通過使用取消標記,他們可以阻止進一步的消息。因此,如果您有一個允許取消的長時間運行的進程,請使用取消標記。另一方面,如果您不希望進程被中斷,那麼使用正常的循環狀態異常,以便在所有線程完成之前吞下異常。

場景3如果您有一個I/O密集型進程,那麼您可能希望使用async/await而不是parallel.foreach。查看微軟的task-based asynchronous pattern

+0

我不確定它是否回答了我何時使用loopState取消的原始問題......您可以分解此答案並解釋它嗎? – webdad3

+0

我欣賞不同的場景。這對我來說更有意義。 – webdad3

2

ParallelLoopState.Break/Stop具有明確定義的特定於循環執行的語義。即通過使用這些,你可以非常具體地瞭解你想如何終止循環。另一方面,CancellationToken是TPL中的通用停止機制,因此它對並行循環沒有任何特殊之處。使用令牌的好處是它可以在其他TPL功能之間共享,因此您可以擁有一個任務和一個由相同標記控制的循環。

+0

實際上,CancellationToken對並行循環有特殊效果。如果ParallelOptions.CancellationToken取消,則ParallelLoopState.ShouldExitCurrentIteration將變爲false。因此,長時間運行的任務(可能未被循環取消)可以檢查該屬性並停止其工作。 https://msdn.microsoft.com/en-us/library/system.threading.tasks.parallelloopstate.shouldexitcurrentiteration(v=vs.110).aspx –