6

Cancellation 操作与 loopState 操作(Break/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 Cancellation 操作而不是loopState.Break();反之亦然loopState.Stop();

4

2 回答 2

2

看这篇文章

“设置取消令牌允许您中止 Invoke(请记住,当委托抛出异常时,异常被吞没,并且只有在所有其他委托都已执行后才由 Invoke 重新抛出)。”

场景 1.假设您有一个用户要向所有前 [女孩|男孩] 朋友发送消息。他们点击发送,然后他们意识到并想要取消它。通过使用取消令牌,他们能够阻止进一步的消息发出。因此,如果您有一个允许取消的长时间运行的进程,请使用取消令牌。

场景 2另一方面,如果您不希望进程被中断,则使用正常的循环状态异常,这样异常将被吞没,直到所有线程完成。

场景 3如果您有一个 I/O 密集型进程,那么您可能希望使用 async/await 而不是 parallel.foreach。查看 Microsoft 的基于任务的异步模式

于 2013-04-16T22:40:40.943 回答
2

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

于 2013-04-17T15:21:08.303 回答