Герберт Шилдт - C# 4.0: полное руководство
- Название:C# 4.0: полное руководство
- Автор:
- Жанр:
- Издательство:ООО И.Д. Вильямс
- Год:2011
- Город:Москва -- Киев
- ISBN:978-5-8459-1684-6
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Герберт Шилдт - C# 4.0: полное руководство краткое содержание
В этом полном руководстве по C# 4.0 - языку программирования, разработанному специально для среды .NET, - детально рассмотрены все основные средства языка: типы данных, операторы, управляющие операторы, классы, интерфейсы, методы, делегаты, индексаторы, события, указатели, обобщения, коллекции, основные библиотеки классов, средства многопоточного программирования и директивы препроцессора. Подробно описаны новые возможности C#, в том числе PLINQ, библиотека TPL, динамический тип данных, а также именованные и необязательные аргументы. Это справочное пособие снабжено массой полезных советов авторитетного автора и сотнями примеров программ с комментариями, благодаря которым они становятся понятными любому читателю независимо от уровня его подготовки.
Книга рассчитана на широкий круг читателей, интересующихся программированием на C#.Введите сюда краткую аннотацию
C# 4.0: полное руководство - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
// метод Break() вместе с методом ForEach() для параллельного выполнения цикла.
using System;
using System.Threading.Tasks;
class DemoParallelForWithLoopResult {
static int[] data;
// Метод, служащий в качестве тела параллельно выполняемого цикла.
// В данном примере переменной v передается значение элемента массива
// данных, а не индекс этого элемента.
static void DisplayData(int v, ParallelLoopState pis) {
// Прервать цикл при обнаружении отрицательного значения,
if (v < 0) pis.Break();
Console.WriteLine("Значение: " + v);
}
static void Main() {
Console.WriteLine("Основной поток запущен.");
data = new int[100000000];
// Инициализировать данные.
for (int i=0; i < data.Length; i++) data[i] = i;
// Поместить отрицательное значение в массив data,
data[100000] = -10;
// Использовать цикл, параллельно выполняемый методом ForEach(),
// для отображения данных на экране.
ParallelLoopResult loopResult = Parallel.ForEach(data, DisplayData);
// Проверить, завершился ли цикл,
if(!loopResult.IsCompleted)
Console.WriteLine("\nЦикл завершился преждевременно из-за того, " +
"что обнаружено отрицательное значение" +
"на шаге цикла номер " +
loopResult.LowestBreakIteration + ".\n");
Console.WriteLine("Основной поток завершен.");
}
}
В приведенной выше программе именованный метод применяется в качестве делегата, представляющего "тело" цикла. Но иногда удобнее применять анонимный метод. В качестве примера ниже приведено реализуемое в виде лямбда-выражения "тело" цикла, параллельно выполняемого методом ForEach()
.
// Использовать цикл, параллельно выполняемый методом ForEach(),
// для отображения данных на экране.
ParallelLoopResult loopResult =
Parallel.ForEach(data, (v, pis) => {
Console.WriteLine("Значение: " + v);
if (v < 0) pis.Break();
}
);
Исследование возможностей PLINQ
PLINQ представляет собой параллельный вариант языка интегрированных запросов LINQ и тесно связан с библиотекой TPL. PLINQ применяется, главным образом, для достижения параллелизма данных внутри запроса. Как станет ясно из дальнейшего, сделать это совсем не трудно. Как и TPL, тема PLINQ довольно обширна и многогранна, поэтому в этой главе представлены лишь самые основные понятия данного языка.
Основу PLINQ составляет класс ParallelEnumerable
, определенный в пространстве имен System.Linq
. Это статический класс, в котором определены многие методы расширения, поддерживающие параллельное выполнение операций. По существу, он представляет собой параллельный вариант стандартного для LINQ класса Enumerable. Многие его методы являются расширением класса ParallelQuery
, а некоторые из них возвращают объект типа ParallelQuery
. В классе ParallelQuery
инкапсулируется последовательность операций, поддерживающая параллельное выполнение. Имеются как обобщенный, так и необобщенный варианты данного класса. Мы не будем обращаться к классу ParallelQuery
непосредственно, а воспользуемся несколькими методами класса ParallelEnumerable
. Самый главный из них, метод AsParallel()
, описывается в следующем разделе.
Едва ли не самым удобным средством PLINQ является возможность просто создавать параллельный запрос. Нужно лишь вызвать метод AsParallel()
для источника данных. Метод AsParallel()
определен в классе ParallelEnumerable
и возвращает источник данных, инкапсулированный в экземпляре объекта типа ParallelQuery
. Это дает возможность поддерживать методы расширения параллельных запросов. После вызова данного метода запрос разделяет источник данных на части и оперирует с каждой из них таким образом, чтобы извлечь максимальную выгоду из распараллеливания. (Если распараллеливание оказывается невозможным или неприемлемым, то запрос, как обычно, выполняется последовательно.) Таким образом, добавления в исходный код единственного вызова метода AsParallel()
оказывается достаточно для того, чтобы превратить последовательный запрос LINQ в параллельный запрос LINQ. Для простых запросов это единственное необходимое условие.
Существуют как обобщенные, так и необобщенные формы метода AsParallel()
. Ниже приведена простейшая обобщенная его форма:
public static ParallelQuery AsParallel(this IEnumerable source)
public static ParallelQuery
AsParallel(this IEnumerable source)
где TSource обозначает тип элементов в последовательном источнике данных source.
Ниже приведен пример, демонстрирующий простой запрос PLINQ.
// Простой запрос PLINQ.
using System;
using System.Linq;
class PLINQDemo {
static void Main() {
int[] data = new int[10000000];
// Инициализировать массив данных положительными значениями,
for(int i=0; i < data.Length; i++) data[i] = i;
//А теперь ввести в массив данных ряд отрицательных значений
data[1000] = -1;
data[14000] = -2;
data[15000] = -3;
data[676000] = -4;
data[8024540] = -5;
data[9908000] = -6;
// Использовать запрос PLINQ для поиска отрицательных значений,
var negatives = from val in data.AsParallel() where val < 0 select val;
foreach(var v in negatives)
Console.Write(v + " ");
Console.WriteLine();
}
}
Эта программа начинается с создания крупного массива data
, инициализируемого целыми положительными значениями. Затем в него вводится ряд отрицательных значений. А далее формируется запрос на возврат последовательности отрицательных значений. Ниже приведен этот запрос.
var negatives = from val in data.AsParallel() where val < 0 select val;
В этом запросе метод AsParallel()
вызывается для источника данных, в качестве которого служит массив data
. Благодаря этому разрешается параллельное выполнение операций над массивом data
, а именно: поиск отрицательных значений параллельно в нескольких потоках. По мере обнаружения отрицательных значений они добавляются в последовательность вывода. Это означает, что порядок формирования последовательности вывода может и не отражать порядок расположения отрицательных значений в массиве data. В качестве примера ниже приведен результат выполнения приведенного выше кода в двухъядерной системе.
Интервал:
Закладка: