This topic has not yet been rated - Rate this topic

How to: Cancel a Parallel.For or ForEach Loop

The Parallel.For and Parallel.ForEach methods support cancellation through the use of cancellation tokens. For more information about cancellation in general, see Cancellation. In a parallel loop, you supply the CancellationToken to the method in the ParallelOptions parameter and then enclose the parallel call in a try-catch block.

The following example shows how to cancel a call to Parallel.ForEach. You can apply the same approach to a Parallel.For call.


namespace CancelParallelLoops
{
    using System;
    using System.Linq;
    using System.Threading;
    using System.Threading.Tasks;

    class Program
    {
        static void Main()
        {
            int[] nums = Enumerable.Range(0, 10000000).ToArray();
            CancellationTokenSource cts = new CancellationTokenSource();

           // Use ParallelOptions instance to store the CancellationToken
            ParallelOptions po = new ParallelOptions();
            po.CancellationToken = cts.Token;
            po.MaxDegreeOfParallelism = System.Environment.ProcessorCount;
            Console.WriteLine("Press any key to start. Press 'c' to cancel.");
            Console.ReadKey();

            // Run a task so that we can cancel from another thread.
            Task.Factory.StartNew(() =>
            {
                if (Console.ReadKey().KeyChar == 'c')
                    cts.Cancel();
                Console.WriteLine("press any key to exit");
            });

            try
            {
                Parallel.ForEach(nums, po, (num) =>
                {
                    double d = Math.Sqrt(num);
                    Console.WriteLine("{0} on {1}", d, Thread.CurrentThread.ManagedThreadId);
                    po.CancellationToken.ThrowIfCancellationRequested();
                });
            }
            catch (OperationCanceledException e)
            {
                Console.WriteLine(e.Message);
            }

            Console.ReadKey();
        }
    }
}


If the token that signals the cancellation is the same token that is specified in the ParallelOptions instance, then the parallel loop will throw a single OperationCanceledException on cancellation. If some other token causes cancellation, the loop will throw an AggregateException with an OperationCanceledException as an InnerException.

Did you find this helpful?
(1500 characters remaining)
Community Content Add
Annotations FAQ
ThrowIfCancellationRequested not need in the example?
It seems for me that ThrowIfCancellationRequested is not need in the example. For and ForEach internals throw the same exception when cancellation happens, if ParallelOptions passed into it.