В чем разница между loopstate.Break(), loopState.Stop() и CancellationTokenSource.Cancel()

У меня есть простой вопрос: у меня есть простой цикл Parallel for. это для цикла является частью службы Windows. Я хочу остановить цикл, когда кто-то останавливает службу. Я могу найти три способа остановить параллель, которая находится в состоянии if. Каков наилучший способ остановить параллель для цикла и каковы различия?

       CancellationTokenSource cancellationToken = new CancellationTokenSource();
       ParallelOptions options = new ParallelOptions();
       options.CancellationToken = cancellationToken.Token;

       Parallel.For(0, maximum_operations, options, (a, loopState) =>
        {
            {
                //Do something

                if(!KeepProcessing)
                { 
                    //loopState.Break();
                    //loopState.Stop();
                    cancellationToken.Cancel();

                }
            }
        });

Ответ 1

CancellationToken используется для отмены сигнала.

loopState.Break() и loopState.Stop() используются для завершения выполнения.

Здесь пример

Parallel.For(0, maximum_operations, options, (a, loopState) =>
    {
        // do work

        // cancellationToken.Cancel() should be called externally
        if(token.IsCancellationRequested)
        {
            // cancellation requested - perform cleanup work if necessary

            // then call
            loopState.Break();
            // or
            loopState.Stop();
        }
    });

loopState.Break() означает завершение всех итераций для всех потоков, которые предшествуют текущей итерации текущего потока, а затем выход из цикла (MSDN).

loopState.Stop() означает остановить все итерации как можно быстрее (MSDN).


Другим способом прекратить выполнение является вызов token.ThrowIfCancellationRequested(), но вам нужно обработать исключение OperationCanceledException:

public void MyMethod()
{
    try
    {
        Parallel.For(0, maximum_operations, options, (a, loopState) =>
        {
            // do work

            token.ThrowIfCancellationRequested();
        });
    }
    catch (OperationCanceledException)
    {
        // handle cancellation
    }
}

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

Например:

  • Необходимо ли немедленно прекратить выполнение, когда ваша служба Windows остановлена? Затем вы можете использовать token.ThrowIfCancellationRequested()
  • Описан ли ваш цикл с объектами IDisposable, которые нуждаются в очистке? Затем вы можете использовать loopState.Break() или loopState.Stop()

Некоторые статьи для справки: