
- •А.А. Волосевич
- •1. Работа с Числами
- •2. Дата и время
- •3. Работа со строками и текстом
- •4. Преобразование информации
- •5. Отношения равенства и порядка
- •Сравнение для выяснения равенства
- •Сравнение для выяснения порядка
- •6. Жизненный цикл объектов
- •Алгоритм «сборки мусора»
- •Финализаторы и интерфейс iDisposable
- •7. Перечислители и итераторы
- •8. Интерфейсы стандартных коллекций
- •9. Массивы и класс system.Array
- •10. Типы для работы с коллекциями-списками
- •11. Типы для работы с коллекциями-множествами
- •12. Типы для работы с коллекциями-словарями
- •13. Типы для создания пользовательских коллекций
- •14. Технология linq to objects
- •1. Оператор условия Where().
- •2. Операторы проекций.
- •3. Операторы упорядочивания.
- •4. Оператор группировки GroupBy().
- •5. Операторы соединения.
- •6. Операторы работы с множествами.
- •7. Операторы агрегирования.
- •8. Операторы генерирования.
- •9. Операторы кванторов и сравнения.
- •10. Операторы разбиения.
- •11. Операторы элемента.
- •12. Операторы преобразования.
- •15. Работа с объектами файЛовой системы
- •16. Ввод и вывод информации
- •Потоки данных и декораторы потоков
- •2. Классы для работы с потоками, связанными с хранилищами.
- •3. Декораторы потоков.
- •4. Адаптеры потоков.
- •Адаптеры потоков
- •17. Основы xml
- •18. Технология linq to xml
- •Создание, сохранение, загрузка xml
- •Запросы, модификация и трансформация xml
- •Пространства имён xml
- •19. ДОполнительные возможности обработки xml
- •20. Сериализация
- •Сериализация времени выполнения
- •Сериализация контрактов данных
- •21. Состав и взаимодействие сборок
- •22. Метаданные и получение информации о типах
- •23. Позднее связывание и кодогенерация
- •24. Динамические типы
- •25. Атрибуты
- •26. Файлы конфигуРации
- •27. Основы мНогопоточноГо программирования
- •28. Синхронизация потоков
- •29. Библиотека параллельных расширений
- •Параллелизм на уровне задач
- •Параллелизм при императивной обработке данных
- •Параллелизм при декларативной обработке данных
- •Обработка исключений и отмена выполнения задач
- •Коллекции, поддерживающие параллелизм
- •30. Асинхронный вызов методов
- •31. Процессы и домены
- •32. Безопасность
- •Разрешения на доступ
- •Изолированные хранилища
- •Криптография
- •33. Диагностика
Параллелизм при императивной обработке данных
Класс System.Threading.Tasks.Parallel позволяет распараллеливать циклы и последовательность блоков кода. Эта функциональность реализована как набор статических методов For(), ForEach() и Invoke().
Методы Parallel.For() и Parallel.ForEach() являются параллельными аналогами циклов for и foreach. Их использование корректно в случае независимости итераций цикла, то есть, если ни в одной итерации не используется результаты работы предыдущих итераций.
Существует несколько перегруженных вариантов метода Parallel.For(), однако любой из них подразумевает указание начального и конечного значения счётчика (тип int или long) и тела цикла в виде объекта делегата. В качестве примера использования Parallel.For() приведём метод, выполняющий перемножение двух квадратных матриц.
public void Multiply(int size, int[,] m1, int[,] m2, int[,] result)
{
Parallel.For(0, size, i =>
{
for (int j = 0; j < size; j++)
{
result[i, j] = 0;
for (int k = 0; k < size; k++)
{
result[i, j] += m1[i, k] * m2[k, j];
}
}
});
}
Метод Parallel.ForEach() имеет множество перегрузок. Простейший вариант предполагает указание коллекции, реализующей IEnumerable<T>, и объекта делегата Action<T>, описывающего тело цикла:
Parallel.ForEach(Directory.GetFiles(path, "*.jpg"), img => Process(img));
Статический метод Parallel.Invoke() позволяет распараллелить исполнение блоков операторов. Часто в приложениях существуют такие последовательности операторов, для которых не имеет значения порядок выполнения операторов внутри них. В таких случаях вместо последовательного выполнения операторов одного за другим, возможно их параллельное выполнение, позволяющее сократить время решения задачи. В базовом варианте Invoke() принимает параметр-список объектов делегата Action:
Parallel.Invoke(DoSomeWork, // DoSomeWork - это некий метод
DoAnotherWork, // DoAnotherWork - некий метод
() => Console.WriteLine("Working..."));
В заключение заметим, что каждый из методов For(), ForEach() и Invoke() может принимать аргумент типа ParallelOptions, используемый для настройки поведения метода.
Параллелизм при декларативной обработке данных
PLINQ (Parallel Language-Integrated Query) ‑ параллельная реализация LINQ, в которой запросы выполняются параллельно, используя все доступные ядра и процессоры. PLINQ полностью поддерживает все операторы запросов, имеющиеся в LINQ to Objects, и имеет минимальное влияние на существующую модель LINQ-операторов.
Рассмотрим простой пример использования PLINQ. Предположим, что имеется медленный метод, который проверяет делимость целого числа на 5:
public static bool IsDivisibleBy5(int x)
{
Thread.Sleep(100);
return x % 5 == 0;
}
Подсчитаем количество чисел, которые делятся на 5, в заданном интервале при помощи обычного LINQ:
var numbers = Enumerable.Range(1, 100);
int count = numbers.Where(IsDivisibleBy5).Count();
Console.WriteLine(count);
Чтобы распараллелить этот запрос средствами PLINQ, достаточно применить к источнику данных (numbers) метод расширения AsParallel():
var numbers = Enumerable.Range(1, 100);
int count = numbers.AsParallel().Where(IsDivisibleBy5).Count();
Console.WriteLine(count);
Почему работоспособен приведённый выше код? В пространстве имён System.Linq содержится статический класс ParallelEnumerable. Он имеет набор методов расширения, аналогичный набору класса Enumerable, но расширяющих класс ParallelQuery<T>. Метод расширения AsParallel() просто «конвертирует» коллекцию IEnumerable<T> в объект ParallelQuery<T>.
Кроме AsParallel(), класс ParallelEnumerable содержит ещё несколько особых методов:
-
AsSequential() ‑ конвертирует объект ParallelQuery<T> в коллекцию IEnumerable<T> так, что все запросы выполняются последовательно;
-
AsOrdered() ‑ при параллельной обработке заставляет сохранять в ParallelQuery<T> порядок элементов;
-
AsUnordered() ‑ при параллельной обработке позволяет игнорировать в ParallelQuery<T> порядок элементов;
-
WithCancellation() ‑ устанавливает для ParallelQuery<T> указанное значение токена отмены;
-
WithDegreeOfParallelism() ‑ устанавливает для ParallelQuery<T> целочисленное значение степени параллелизма (число ядер процессоров);
-
WithExecutionMode() ‑ задаёт опции выполнения параллельных запросов в виде перечисления ParallelExecutionMode.
int count = numbers.AsParallel().
AsOrdered().
WithExecutionMode(ParallelExecutionMode.ForceParallelism).
Where(IsDivisibleBy5).Count();