Concurrenc in C# Cookbook / Конкурентность в C# книга рецептов: Обзор конкурентного программирования
| Английский оригинал | Перевод на русский | |
|---|---|---|
Сожалеем, но текст оригинала доступен только зарегистрированным пользователям. |
До тех пор пока части выполняемой параллельно работы независимы друг от друга степень параллелизма максимальна. Однако как только вы предпринимаете попытки совместного использования состояния несколькими потоками, вы должны синхронизировать доступ к общему состоянию,что приводит к значительному снижению практической пользы параллелизма данных. Мы рассмотрим синхронизацию более подробно в 11 главе. masterofsea147 31.01.20 в 23:24 |
|
|
<Результаты параллельной работы могут быть <обработаны> различными способами. Вы можете поместить их в какую-нибудь конкурентную коллекцию или объединить их в <сводку>. Агрегация - это основа параллельной обработки; этот вид map / reduce функциональности также поддерживается перегрузками метода класса Parallel. Рассмотрим агрегацию детальнее в рецепте 3.2.> masterofsea147 01.02.20 в 12:24 |
||
|
Теперь давайте перейдем к параллелизму задач. Параллелизм данных ориентирован на обработку данных; параллелизм задач - это просто параллельное выполнение задач. masterofsea147 30.01.20 в 15:36 |
+1 | |
|
Один из методов класса Parralel реализует параллелизм задач типа разделение/соединение (fork/join) - это метод Parallel.Invoke. Пример его работы показан в рецепте 3.3; нужно всего лишь передать ему делегатов для их параллельного выполнения: <listing8> masterofsea147 31.01.20 в 23:19 |
||
|
Тип Task изначально был предназначен для параллелизма задач, однако теперь он также используется для асинхронного программирования. Экземпляр типа Task при использовании с параллелизмом задач - инкапсулирует в себе часть работы. Чтобы дождаться завершения задачи вы можете использовать метод Wait, в свою очередь, чтобы получить результаты выполнения этой задачи вы можете использовать свойства Result и Exception. Использование класса Task напрямую, сложнее, чем работа с типом Parallel, но он может быть полезен, если структура параллелизма не известна заранее (до начала времени исполнения). <При таком динамическом параллелизме вы не знаете, сколько частей вам нужно выполнить в начале обработки; Вы узнаете об этом по ходу дела>. Как правило, динамическая часть работы должна запускать любые дочерние задачи, в которых она нуждается, и затем ждать их завершения. Тип Task имеет для этого специальный флаг TaskCreationOptions.AttachedToParent. Динамический параллелизм описан в рецепте 3.4. masterofsea147 01.02.20 в 13:35 |
||
|
При параллелизме задач отдельно взятые части параллельного исполнения должны стремиться к абсолютной независимости друг от друга, как и при параллелизме данных. Чем более независимыми будут ваши делегаты, тем эффективнее может быть ваша программа. При параллелизме задач требуется соблюдать особенную осторожность с захваченными переменными в замыканиях. Не забывайте, что замыкания захватывают ссылки (а не значения), поэтому вы можете получить общий доступ, который не очевиден и может привести к проблемам потокобезопасности. masterofsea147 01.02.20 в 13:41 |
||
|
Обработка ошибок одинакова при всех видах параллелизма. Поскольку операции выполняются параллельно, возможно возникновение нескольких исключений одновременно. Они заключаются в экземпляр специального типа AggregateException. Это поведение одинаково для Parallel.ForEach, Parallel.Invoke, Task.Wait и т.д. Тип AggregateException имеет несколько полезных методов Flatten и Handle, предназначенных для упрощения процесса обработки ошибок: <listing9> masterofsea147 01.02.20 в 15:32 |
||
|
Задачи не должны быть ни слишком короткими, ни слишком длинными. masterofsea147 01.02.20 в 15:34 |
||
|
Если вы хотите глубже изучить параллельное программирование, то я рекомендую вам прочитать лучшую книгу на эту тему - masterofsea147 01.02.20 в 15:38 |
||
|
Parallel Programming with Microsoft .NET, by Colin Campbell et al. (MSPress). masterofsea147 01.02.20 в 15:38 |
||
|
1.4. Введение в реактивное программирование (Rx) masterofsea147 01.02.20 в 15:38 |
||
|
Реактивное программирование является наиболее сложным в изучении типом конкурентности, его код сложнее поддерживать, если ваши навыки реактивного программирования еще не достаточно высоки. Если вы его изучите, оно станет вашим чрезвычайно мощным инструментом. Реактивное программирование позволяет вам обрабатывать поток событий как поток данных. Как правило, <если вы используете какой-либо из аргументов, передаваемых событию, тогда ваш код выиграет от использования Rx вместо обычного обработчика события.> masterofsea147 01.02.20 в 15:58 |
||
|
Реактивное программирование основано на понятии наблюдаемых потоков. <Когда вы подписываетесь на наблюдаемый поток, вы получите любое количество элементов данных (OnNext), и тогда поток может завершиться с одной ошибкой (OnError) или уведомлением об окончании потока (OnCompleted). Некоторые из наблюдаемых потоков не прекращаются>. Вот как выглядит их интерфейс: <listing9> masterofsea147 01.02.20 в 16:23 |
||
