ArcticWolf_11
ArcticWolf_11

Reputation: 99

How Do I Break Out Of A Parallel.For Loop When One Thread Matches An If Statement?

so in my program I want the first thread that finishes first's value to be displayed in console and then have it so that all remaining threads are then aborted. Here is the code that I have now that demonstrates the issue.

    public static void test()
    {
        int Loop = 0;

        Parallel.For(0, 2000, new ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount }, (i, End) =>
        {
            Loop++;
            Console.WriteLine(Loop);

            if (Loop == 1000)
            {
                Console.WriteLine("Break!");
                End.Break();
            }
        });
    }

And when it's done here is a snippet of what gets outputted into the console

985
987
983
Break!
Break!
992
998
Break!
Break!
00:00:00.7217394

So right now I have no idea how to get it to stop all together when one thread matches the if statement. Any help would be greatly appreciated!

Upvotes: 2

Views: 440

Answers (2)

vasily.sib
vasily.sib

Reputation: 4002

Another option is to use ParallelLoopState.Stop() method. I have tested it with empty Console application:

Parallel.For(0, 2000, new ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount },
    (i, state) =>
    {
        Console.Write($"{i}, ");

        if (i == 1000)
        {
            Console.Write("STOP! ");
            state.Stop();
        }
    });

The untruncated output was:

0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 1000, STOP! 580, 1500, 16,

Almost same result as with CancellationToken, except you don't have to handle OperationCanceledException.

There is also a ParallelLoopState.Break() method. Which is slightly different. It stops execution of all future iterations of loop. So in this case, you will not see any numbers more then 1000 after STOP! text, but they still may be present before it.

Upvotes: 4

user585968
user585968

Reputation:

Parallel.Forxxx support CancellationTokens. Just create a CancellationTokenSource, assign it to an instance of ParallelOptions and during your loop, you can just trigger it when desired.

public static void test()
{
    int Loop = 0;

    CancellationTokenSource cts = new CancellationTokenSource();

    try
    {
        Parallel.For(0, 2000, 
              new ParallelOptions() 
              { 
                  MaxDegreeOfParallelism = Environment.ProcessorCount, 
                 CancellationToken = cts.Token 
              }, 
        (i, End) =>
        {
            cts.Token.ThrowIfCancellationRequested();

            // ...

            if (i == 1000) // you should be using 'i'
            {
                Console.WriteLine("Break!");
                cts.Cancel();
            }
        });
    }
    catch (OperationCanceledException )
    {
        // expected behaviour
    }
}

As TheGeneral said, your loop isn't thread safe so I have made some changes and left a space for you to fill.

Tell me More

Upvotes: 4

Related Questions