Console.WriteLine("Основной поток запущен.");
data = new int[100000000];
// Инициализировать данные.
for(int i=0; i < data.Length; i++) data[i] = i;
// Поместить отрицательное значение в массив data, data[1000] = -10;
// Параллельный вариант инициализации массива в цикле.
ParallelLoopResult loopResult = Parallel.For(0, data.Length, MyTransform);
// Проверить, завершился ли цикл,
if(!loopResult.IsCompleted)
Console.WriteLine("\nЦикл завершился преждевременно из-за того, " +
"что обнаружено отрицательное значение" +
"на шаге цикла номер " +
loopResult.LowestBreakIteration + ".\n");
Console.WriteLine("Основной поток завершен.");
}
}
Выполнение этой программы может привести, например, к следующему результату.
Основной поток запущен.
Цикл завершился преждевременно из-за того, что обнаружено отрицательное значение на шаге цикла номер 1000
Основной поток завершен.
Как следует из приведенного выше результата, цикл преобразования данных преждевременно завершается после 1000 шагов. Дело в том, что метод Break()
вызывается внутри метода MyTransform()
при обнаружении в массиве данных отрицательного значения.
Помимо двух описанных выше форм метода For(
) существует и ряд других его форм. В одних из этих форм допускается указывать различные дополнительные параметры, а в других — использовать параметры типа long
вместо int
для пошагового выполнения цикла. Имеются также формы метода For()
, предоставляющие такие дополнительные преимущества, как, например, возможность указывать метод, вызываемый по завершении потока каждого цикла.
И еще одно, последнее замечание: если требуется остановить цикл, параллельно выполняемый методом For()
, не обращая особого внимания на любые шаги цикла, которые еще могут быть в нем выполнены, то для этой цели лучше воспользоваться методом Stop()
, чем методом Break()
.
Используя метод ForEach()
, можно создать распараллеливаемый вариант цикла foreach
. Существует несколько форм метода ForEach()
. Ниже приведена простейшая форма его объявления:
public static ParallelLoopResult
ForEach
Action
где IEnumerable
. Метод, передаваемый через параметр
Аналогично методу For()
, параллельное выполнение цикла методом ForEach()
можно остановить, вызвав метод Break()
для экземпляра объекта типа ParallelLoopState
, передаваемого через параметр body
, при условии, что используется приведенная ниже форма метода ForEach()
.
public static ParallelLoopResult
ForEach
Action
В приведенном ниже примере программы демонстрируется применение метода ForEach()
на практике. Как и прежде, в данном примере создается крупный массив целых значений. А отличается данный пример от предыдущих тем, что метод, выполняющийся на каждом шаге цикла, просто выводит на консоль значения из массива. Как правило, метод WriteLine()
в распараллеливаемом цикле не применяется, потому что ввод-вывод на консоль осуществляется настолько медленно, что цикл оказывается полностью привязанным к вводу-выводу. Но в данном примере метод WriteLine()
применяется исключительно в целях демонстрации возможностей метода ForEach()
. При обнаружении отрицательного значения выполнение цикла прерывается вызовом метода Break()
. Несмотря на то что метод Break()
вызывается в одной задаче,