如何停止Parallel.ForEach循环?

时间:2016-09-29 18:31:17

标签: c#

我有这个代码来启动Parallel 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放在哪里。

谢谢!

4 个答案:

答案 0 :(得分:5)

重写如下

function filter_devices() {
    return n=>n.type != "mobile device";
}

希望这有帮助。

答案 1 :(得分:1)

我认为使用此overload应该有效:

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

答案 2 :(得分:0)

尝试使用此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();
        }

或者不是直接设置CallToStop = true来电cts.Cancel()

或者你可以取消注释// 1并让所有没有完成的threds抛出OperationCanceledException(仅当你因为CallToStop = true由于cts.Token而停止所有并行线程时才使用。)

您甚至可以将internalProcessStart(item,token)传递到Parallel.ForEach<ListViewItem>(filesListView.Items.Cast<ListViewItem>(), new ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount }, (item, state) => { if (CallToStop == true) { state.Break(); } internalProcessStart(item); }); ,并处理在内部流程已经运行时取消的操作。

答案 3 :(得分:0)

尝试这样的事情。从概念上讲,您需要将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;
                }
            });