Parallel.Invoke(() => {
Console.WriteLine("Выражение #1 запущено");
for(int count = 0; count < 5; count++) {
Thread.Sleep(500);
Console.WriteLine("В выражении #1 подсчет равен " + count );
}
Console.WriteLine("Выражение #1 завершено");
},
() => {
Console.WriteLine("Выражение #2 запущено");
for (int count = 0; count < 5; count++) {
Thread.Sleep(500);
Console.WriteLine("В выражении #2 подсчет равен " + count );
}
Console.WriteLine("Выражение #1 завершено");
} );
Console.WriteLine("Основной поток завершен.");
}
}
Эта программа дает результат, похожий на результат выполнения предыдущей программы.
В TPL параллелизм данных поддерживается, в частности, с помощью метода For()
, определенного в классе Parallel
. Этот метод существует в нескольких формах. Его рассмотрение мы начнем с самой простой формы, приведенной ниже:
public static ParallelLoopResult
For(int fromlnclusive, int toExclusive, Action
где Action
, объявляемым следующим образом.
public delegate void Action
For()
обобщенный параметр Т должен быть, конечно, типа int
. Значение, передаваемое через параметр For()
возвращает экземпляр объекта типа ParallelLoopResult
, описывающий состояние завершения цикла. Для простых циклов этим значением можно пренебречь. (Более подробно это значение будет рассмотрено несколько ниже.)
Главная особенность метода For()
состоит в том, что он позволяет, когда такая возможность имеется, распараллелить исполнение кода в цикле. А это, в свою очередь, может привести к повышению производительности. Например, процесс преобразования массива в цикле может быть разделен на части таким образом, чтобы разные части массива преобразовывались одновременно. Следует, однако, иметь в виду, что повышение производительности не гарантируется из-за отличий в количестве доступных процессоров в разных средах выполнения, а также из-за того, что распараллеливание мелких циклов может составить издержки, которые превышают сэкономленное время.
В приведенном ниже примере программы демонстрируется применение метода For()
на практике. В начале этой программы создается массив data
, состоящий из 1000000000 целых значений. Затем вызывается метод For()
, которому в качестве "тела" цикла передается метод MyTransfогm()
. Этот метод состоит из ряда операторов, выполняющих произвольные преобразования в массиве data
. Его назначение — сымитировать конкретную операцию. Как будет подробнее пояснено несколько ниже, выполняемая операция должна быть нетривиальной, чтобы параллелизм данных принес какой-то положительный эффект. В противном случае последовательное выполнение цикла может завершиться быстрее.
// Применить метод Parallel.For() для организации параллельно
// выполняемого цикла обработки данных.
using System;
using System.Threading.Tasks;
class DemoParallelFor {
static int[] data;
// Метод, служащий в качестве тела параллельно выполняемого цикла.
// Операторы этого цикла просто расходуют время ЦП для целей демонстрации,
static void MyTransform(int i) {
data[i] = data[i] / 10;
if(data[i] < 10000) data[i] = 0;
if(data[i] > 10000 & data[i] < 20000) data[i] = 100;