简体   繁体   中英

How to stop a Parallel.ForEach loop?

I have this code to start a Parallel ForEach loop:

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

I have some code which will check if there is a call to stop the threads, and then I would like to break; the code, but this doesn't work with Parallel.

I found the same question by someone else , but their code is slighly different to mine, and I'm not sure where to put the ParallelLoopState state .

Thanks!

Rewrite as below

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

Hope this helps.

I think using this overload should work:

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

Try using CancellationToken as in this example (MSDN) .

Try something like this:

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();
        }

Or instead of setting CallToStop = true call cts.Cancel() directly.

Or you can uncomment //1 and let all threds that did not finished throw OperationCanceledException (only use whenyou are stopping all parallel thread because of CallToStop = true is caused by error).

You can even pass the cts.Token into your internalProcessStart(item,token) and handle what to do if you cancel when internal process is already running.

Try something like this. Conceptually, you need to pass the loopState to your lambda function.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM