Контексты

В этом документе описана роль контекстов в среде выполнения с параллелизмом. Поток, прикрепленный к планировщику, известен как контекст выполнения или просто контекст. Функция Concurrency::wait и класс Concurrency::Context позволяют управлять поведением контекстов. Функция wait приостанавливает текущий контекст на заданный период времени. Класс Context позволяет управлять контекстами, когда они блокируются, разблокируются и передают выполнение, а также если нужно превысить лимит подписки текущего контекста.

Совет

Среда выполнения с параллелизмом предоставляет планировщик по умолчанию, поэтому вам не обязательно создавать собственный.Так как планировщик заданий помогает оптимизировать производительность приложений, рекомендуется начать с раздела Библиотека параллельных шаблонов или Библиотека асинхронных агентов, если вы не знакомы со средой выполнения с параллелизмом.

Функция wait

Функция Concurrency::wait совместно передает выполнение текущего контекста на заданное число миллисекунд. Среда выполнения использует время передачи для выполнения других задач. По истечении заданного времени среда выполнения перепланирует контекст для выполнения. Следовательно, продолжительность приостановки текущего контекста функцией wait может быть больше, чем значение параметра milliseconds.

Если параметру milliseconds передано значение 0 (нуль), среда выполнения приостанавливает текущий контекст до тех пор, пока другие активные контексты не получат возможность выполнять работу. Это позволяет передать задачу всем другим активным задачам.

Пример

Пример, в котором функция wait используется для передачи текущего контекста и, следовательно, позволяет выполняться другим контекстам, см. в разделе Практическое руководство. Использование групп расписаний для определения порядка выполнения.

Класс Context

Класс Concurrency::Context предоставляет программную абстракцию для контекста выполнения, а также две важные функции: возможность совместно блокировать, разблокировать и передавать текущий контекст и возможность превышать лимит подписки текущего контекста.

Совместное блокирование

Класс Context позволяет блокировать или разрешать текущий контекст выполнения. Блокирование и передача полезны, если текущий контекст не может продолжать работу из-за недоступности ресурса.

Метод Concurrency::Context::Block блокирует текущий контекст. Заблокированный контекст передает свои ресурсы для обработки, чтобы среда выполнения могла выполнить другие задачи. Метод Concurrency::Context::Unblock разблокирует заблокированный контекст. Методы Context::Unblock и Context::Block должны вызываться из разных контекстов. Среда выполнения создает исключение Concurrency::context_self_unblock, если контекст пытается разблокировать себя.

Как правило, чтобы совместно заблокировать и разблокировать контекст, вызывается метод Concurrency::Context::CurrentContext для извлечения указателя на объект Context, связанный с текущим потоком, и сохранения результата. Затем необходимо вызвать метод Context::Block для блокирования текущего контекста. После этого для разблокирования заблокированного контекста необходимо вызвать метод Context::Unblock из отдельного контекста.

Необходимо сопоставить каждую пару вызовов методам Context::Block и Context::Unblock. Среда выполнения создает исключение Concurrency::context_unblock_unbalanced, если метод Context::Block или Context::Unblock вызывается последовательно без соответствующего вызова другого метода. Однако не обязательно вызывать метод Context::Block до вызова метода Context::Unblock. Например, если один контекст вызывает метод Context::Unblock до того, как другой контекст вызовет метод Context::Block для того же контекста, контекст остается незаблокированным.

Метод Concurrency::Context::Yield передает выполнение, чтобы среда выполнения могла работать над другими задачами, а затем перепланировать контекст для выполнения. При вызове метода Context::Block среда выполнения не перепланирует контекст.

Пример

Пример, в котором методы Context::Block, Context::Unblock и Context::Yield используются для реализации класса семафора, поддерживающего параллельный доступ, см. в разделе Практическое руководство. Использование класса Context для реализации семафора, поддерживающего параллельный доступ.

Превышение лимита подписки

Число потоков, создаваемых планировщиком по умолчанию, совпадает с числом доступных аппаратных потоков. Превышение лимита подписки можно использовать для создания дополнительных потоков для заданного аппаратного потока.

Как правило, превышение лимита подписки не подходит для выполнения операций с большим объемом вычислений, потому что так создается дополнительная нагрузка на систему. Однако если речь идет о задачах с большими задержками (например, о считывании данных с диска или сетевого подключения), превышение лимита подписки может способствовать повышению общей производительности некоторых приложений.

Примечание

Следует разрешать превышение лимита подписки только в не-UMS потоках, созданных средой выполнения с параллелизмом.Превышение лимита подписки не даст эффекта, если будет вызвано из потока, созданного не средой выполнения с параллелизмом (включая главный поток).Кроме того, превышение лимита подписки не даст эффекта, будучи вызвано из контекста, который использует UMS-потоки для планирования задач, поскольку UMS-потоки позволяют планировщику полностью использовать ресурсы при наличии блокирующих операций.

Чтобы разрешить превышение лимита подписки в текущем контексте, нужно вызвать метод Concurrency::Context::Oversubscribe, параметру _BeginOversubscription которого присвоено значение true. Если превышение лимита подписки разрешено для потока, созданного в среде выполнения с параллелизмом, среда выполнения создает один дополнительный поток. После завершения всех задач, требующих превышения лимита подписки, необходимо вызвать метод Context::Oversubscribe, параметру _BeginOversubscription которого задано значение false.

В текущем контексте можно разрешать превышение лимита подписки несколько раз, при этом запрещать его необходимо столько же раз. Превышение лимита подписки также может быть вложенным; т. е. задача, созданная другой задачей, которая использует превышение лимита подписки, также может превышать лимит подписки своего контекста. Однако если и вложенная задача, и родительская задача принадлежат к одному контексту, дополнительный поток создается только при самом внешнем вызове метода Context::Oversubscribe.

Примечание

Среда выполнения создает исключение Concurrency::invalid_oversubscribe_operation, если превышение лимита подписки запрещено раньше, чем разрешено.

Пример

Пример, в котором превышение лимита подписки используется для смещения задержки, возникающей из-за считывания данных из сетевого подключения, см. в разделе Практическое руководство. Использование лимита подписки для устранения задержек.

См. также

Задачи

Практическое руководство. Использование лимита подписки для устранения задержек

Основные понятия

Планировщик задач (среда выполнения с параллелизмом)

Другие ресурсы

Практическое руководство. Использование групп расписаний для определения порядка выполнения

Практическое руководство. Использование класса Context для реализации семафора, поддерживающего параллельный доступ

Журнал изменений

Дата

Журнал

Причина

Июль 2010

Содержимое реорганизовано.

Улучшение информации.