parallel.foreach - loopState.Stop() против отмены

В чем разница между операциями Cancellation и loopState (Break/Stop)?

private static CancellationTokenSource cts;
public static loopingMethod()
{
cts = new CancellationTokenSource();
try
{
    ParallelOptions pOptions = new ParallelOptions();
    pOptions.MaxDegreeOfParallelism = 4;
    pOptions.CancellationToken = cts.Token;
    Parallel.ForEach(dictObj, pOptions, (KVP, loopState) =>
    {
        pOptions.CancellationToken.ThrowIfCancellationRequested();
        parallelDoWork(KVP.Key, KVP.Value, loopState);
     }); //End of Parallel.ForEach loop
 }
 catch (OperationCanceledException e)
 {
 //Catestrophic Failure
 return -99;
 }
}

public static void parallelDoWork(string Id, string Value, ParallelLoopState loopState)
{
   try{
      throw new exception("kill loop");
   }
   catch(exception ex)
   {
       if(ex.message == "kill loop")
       {
           cts.Cancel();
           //Or do I use loopState here?
       }
   }
}

Зачем мне использовать операцию отмены ParallelOptions вместо операции loopState.Break(); или loopState.Stop(); или наоборот?


person webdad3    schedule 16.04.2013    source источник


Ответы (2)


См. эту статью.

"Установка маркера отмены позволяет прервать Invoke (помните, что когда делегат создает исключение, исключение проглатывается и повторно генерируется Invoke только после выполнения всех других делегатов). сильный>)".

Сценарий 1. Представьте, что у вас есть пользователь, который собирается отправить сообщение всем бывшим [девушкам|парням]друзьям. Нажимают отправить, а потом приходят в себя и хотят отменить. Используя токен отмены, они могут предотвратить отправку дальнейших сообщений. Поэтому, если у вас есть длительный процесс, который можно отменить, используйте токен отмены.

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

Сценарий 3 Если у вас есть процесс с интенсивным вводом-выводом, вы, вероятно, захотите использовать async/await, а не parallel.foreach. Ознакомьтесь с асинхронным шаблоном на основе задач от Microsoft.

person What Would Be Cool    schedule 16.04.2013
comment
Я не уверен, отвечает ли он на первоначальный вопрос о том, когда бы я использовал loopState вместо отмены... Можете ли вы разбить этот ответ и объяснить его подробнее? - person webdad3; 17.04.2013
comment
Я ценю разные сценарии. Это имеет для меня гораздо больше смысла. - person webdad3; 18.04.2013

ParallelLoopState.Break/Stop имеют четко определенную семантику, специфичную для выполнения цикла. т.е. используя их, вы можете очень точно указать, как вы хотите завершить цикл. С другой стороны, CancellationToken — это общий механизм остановки в TPL, поэтому он не делает ничего особенного для параллельных циклов. Преимущество использования токена заключается в том, что его можно использовать совместно с другими функциями TPL, поэтому у вас может быть задача и цикл, управляемые одним и тем же токеном.

person Brian Rasmussen    schedule 17.04.2013
comment
На самом деле CancellationToken оказывает особое влияние на параллельные циклы. Если ParallelOptions.CancellationToken отменен, ParallelLoopState.ShouldExitCurrentIteration становится ложным. Таким образом, длительная задача (которая, возможно, не была отменена циклом) может проверить это свойство и остановить свою работу. msdn.microsoft .com/en-us/library/ - person Cagatay Kalan; 14.05.2017
comment
@CagatayKalan Не уверен, что ваш комментарий верен. Прежде всего, вы, вероятно, имели в виду true, а не false. Во-вторых, ShouldExitCurrentIteration устанавливается в true также при использовании Break или Stop, так что это не только CancellationToken. Кроме того, проверка состояния ShouldExitCurrentIteration автоматически выполняется циклом, и нет необходимости в собственном коде для этого, если только вы не хотите реализовать какую-то специальную логику. - person silkfire; 08.05.2019