Как выйти из цикла Parallel.For, если один поток соответствует оператору If? - PullRequest
0 голосов
/ 02 ноября 2018

поэтому в моей программе я хочу, чтобы первый поток, заканчивающий первое значение, отображался в консоли, а затем имел его, чтобы все оставшиеся потоки были затем прерваны. Вот код, который у меня сейчас есть, который демонстрирует проблему.

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

И когда это будет сделано, приведен фрагмент того, что выводится в консоль

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

Так что сейчас я понятия не имею, как заставить его остановить все вместе, когда один поток соответствует оператору if. Любая помощь будет принята с благодарностью!

Ответы [ 2 ]

0 голосов
/ 02 ноября 2018

Другой вариант - использовать метод ParallelLoopState.Stop () . Я проверил это с пустым консольным приложением:

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

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

Не усеченный вывод был:

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,

Почти тот же результат, что и с CancellationToken, за исключением того, что вам не нужно обрабатывать OperationCanceledException.

Существует также метод ParallelLoopState.Break () . Что немного отличается. Останавливает выполнение всех будущих итераций цикла. Таким образом, в этом случае вы не увидите никаких чисел больше 1000 после STOP! текста, но они все еще могут присутствовать перед ним.

0 голосов
/ 02 ноября 2018

Parallel.Forxxx поддержка CancellationToken с. Просто создайте CancellationTokenSource, назначьте его экземпляру ParallelOptions и во время цикла вы можете просто вызвать его при желании.

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
    }
}

Как сказал TheGeneral , ваш цикл не безопасен для потоков, поэтому я внес некоторые изменения и оставил место для заполнения.

Расскажите подробнее

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...