【问题标题】:How to stop a Parallel.ForEach loop?如何停止 Parallel.ForEach 循环?
【发布时间】:2016-09-29 18:31:16
【问题描述】:

我有这段代码来启动一个并行 ForEach 循环:

Parallel.ForEach<ListViewItem>(filesListView.Items.Cast<ListViewItem>(), new ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount }, item => {
    if (CallToStop == true)
        {  
            //Code here to stop the loop!
        }        
    internalProcessStart(item);
});

我有一些代码可以检查是否有停止线程的调用,然后我想break; 代码,但这不适用于 Parallel。

我找到了相同的 question by someone else,但他们的代码与我的略有不同,我不确定将 ParallelLoopState state 放在哪里。

谢谢!

【问题讨论】:

  • 你也可以在 ForEach 循环体中进行编辑吗?
  • @KevinLe 好的,完成!

标签: c#


【解决方案1】:

改写如下

Parallel.ForEach<ListViewItem>(filesListView.Items.Cast<ListViewItem>(), 
            new ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount }, 
           (item, state) => {
    if (CallToStop == true)
        {  
            state.Break();
        }        
    internalProcessStart(item);
});

希望这会有所帮助。

【讨论】:

  • 谢谢,这是我使用的代码,它运行良好。谢谢
【解决方案2】:

我认为使用这个overload 应该可以:

    Parallel.ForEach<ListViewItem>(filesListView.Items.Cast<ListViewItem>(), new ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount }, (item , state)  => 
    {
        if (/*Stop condition here*/)
        { 
            state.Break(); 
        }        
        internalProcessStart(item);
    });

【讨论】:

    【解决方案3】:

    试试这样的。从概念上讲,您需要将 loopState 传递给您的 lambda 函数。

    Parallel.ForEach<int>(new List<int>(),
                new ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount },
                (val, loopState) =>
                {
                    if (val == 9) //enter your stopcondition here
                    {
                        loopState.Stop();
                        return;
                    }
                });
    

    【讨论】:

      【解决方案4】:

      尝试使用CancellationToken,如example (MSDN)

      试试这样的:

      CancellationTokenSource cts = new CancellationTokenSource();

             // Use ParallelOptions instance to store the CancellationToken
              ParallelOptions po = new ParallelOptions();
              po.CancellationToken = cts.Token;
              po.MaxDegreeOfParallelism = Environment.ProcessorCount;
      
              try
              {
                  Parallel.ForEach<ListViewItem>(filesListView.Items.Cast<ListViewItem>(), po, item => {
                      // po.CancellationToken.ThrowIfCancellationRequested(); //1
                      if (CallToStop == true)
                      {  
                          //Code here to stop the loop!
                          cts.Cancel();
                      }
                      if (po.CancellationToken.IsCancellationRequested == false)
                      {        
                          internalProcessStart(item);
                      }
                  });
              }
              catch (OperationCanceledException e)
              {
                  // handle
              }
              finally
              {
                  cts.Dispose();
              }
      

      或者直接调用cts.Cancel()而不是设置CallToStop = true

      或者你可以取消注释 //1 并让所有未完成的线程抛出OperationCanceledException(仅在你停止所有并行线程时使用,因为CallToStop = true是由错误引起的)。

      您甚至可以将cts.Token 传递给您的internalProcessStart(item,token) 并处理如果您在内部进程已经运行时取消该怎么办。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-05-13
        • 1970-01-01
        • 2022-01-11
        • 2014-05-30
        • 2010-09-26
        • 2012-06-19
        • 2019-07-01
        • 2013-09-11
        相关资源
        最近更新 更多