Ask a questionAsk a question
 

AnswerBreak out of Parallel.Foreach in June CTP

  • Thursday, September 24, 2009 8:27 PMThomas _LA_ Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    How do you break out of a Parallel.Foreach loop in the June CTP? I see that in the .NET 4.0 extensions they have added the ability to do so, but how do you do it in the previous set of extensions?

Answers

  • Saturday, September 26, 2009 12:09 AMStephen Toub - MSFTMSFT, ModeratorUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     AnswerHas Code

    ParallelState is public; its constructor is internal.  But you don't need to construct one.  Rather, the loop constructs one and passes that instance in to your delegate, e.g.

    using System;
    using System.Threading;
    
    class Program
    {
        static void Main(string[] args)
        {
            int[] data = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
            Parallel.ForEach(data, (i, state) =>
            {
                if (i == 4) state.Stop();
                Thread.Sleep(i * 1000);
                Console.WriteLine(i);
            });
        }
    }
    

All Replies

  • Friday, September 25, 2009 1:07 AMStephen Toub - MSFTMSFT, ModeratorUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Proposed Answer
    The June CTP supported this by using an overload of Parallel.ForEach that used a delegate which accepted a ParallelState parameter.  That ParallelState exposed a Stop method, which could be used to exit a loop early.  Throwing an exception would also cause early exit from a loop.
  • Friday, September 25, 2009 4:57 PMThomas _LA_ Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    But the problem is that the ParallelState enumeration is marked as internal. AFAICT, there is no way to create an instance of it.
  • Saturday, September 26, 2009 12:09 AMStephen Toub - MSFTMSFT, ModeratorUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     AnswerHas Code

    ParallelState is public; its constructor is internal.  But you don't need to construct one.  Rather, the loop constructs one and passes that instance in to your delegate, e.g.

    using System;
    using System.Threading;
    
    class Program
    {
        static void Main(string[] args)
        {
            int[] data = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
            Parallel.ForEach(data, (i, state) =>
            {
                if (i == 4) state.Stop();
                Thread.Sleep(i * 1000);
                Console.WriteLine(i);
            });
        }
    }
    
  • Saturday, September 26, 2009 12:14 AMThomas _LA_ Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Ah. Using a undeclared variable called "state" seemingly out of thin-air is definitely not intuitive but with multi-threaded development that seems to be par for the course ;->. Thanks!
  • Saturday, September 26, 2009 12:33 AMStephen Toub - MSFTMSFT, ModeratorUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Happy to help.

    I'm using the most condensed lambda syntax.  If it helps from a clarity perspective, you could expand it to the full delegate syntax:

    Parallel.ForEach(data, delegate(int i, ParallelState state)
    {
         ...
    });

    or even separating out the delegate:

    Action<int, ParallelState> body = delegate(int i, ParallelState state)
    {
        ...
    });
    Parallel.ForEach(data, body);

    Finally, of course, you can separate the body out into its own method.