parallel.foreach - loopState.Stop()与Cancellation

时间:2013-04-16 22:26:43

标签: c# cancellation-token

取消操作与loopState操作(中断/停止)之间有什么区别?

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 个答案:

答案 0 :(得分:2)

请参阅此article

"设置取消令牌允许您中止Invoke(请记住,当委托抛出异常时,吞下异常,并且只有在所有其他委托之后才被Invoke重新抛出的执行)"

场景1。想象一下,您有一个用户即将向所有前女友发送消息。他们点击发送,然后他们发现他们想要取消它。通过使用取消令牌,他们可以阻止进一步的消息。因此,如果您有一个允许取消的长时间运行进程,请使用取消令牌。

场景2 另一方面,如果您不希望中断进程,则使用正常的循环状态异常,以便在所有线程完成之前吞下异常。< / p>

场景3 如果您的进程是I / O密集型的,那么您可能希望使用async / await而不是parallel.foreach。查看Microsoft的task-based asynchronous pattern

答案 1 :(得分:2)

ParallelLoopState.Break / Stop具有明确定义的语义,特定于循环的执行。即通过使用这些,您可以非常具体地了解您希望循环终止的方式。另一方面,CancellationToken是TPL中的通用停止机制,因此它对并行循环没有什么特别之处。使用令牌的优点是它可以在其他TPL功能之间共享,因此您可以拥有一个由同一令牌控制的任务和循环。