С выходом .NET Framework 4.0 в состав BCL была добавлена библиотека Task Parallel Library (TPL), реализующая параллелизм на основе задач. В основе библиотеки лежат типы Task и унаследованный от него тип Task<TResult>. Эти типы являются обёртками для асинхронных операций; они позволяют абстрагироваться от таких технических деталей, как, например, потоки и синхронизировать асинхронные операции друг с другом.
В этой же версии .NET Framework появился мини-framework для кооперативной отмены асинхронных операций. Состоит он из всего трёх типов:
- CancellationTokenSource — создаёт маркёры отмены (свойство Token) и обрабатывает запросы на отмену операции (перегруженные методы Cancel/CancelAfter).
- CancellationToken — маркёр отмены; позволяет несколькими способами отслеживать запросы на отмену операции: опросом свойства IsCancellationRequested, регистрацией callback-функции (через перегруженный метод Register), ожиданием на объекте синхронизации (свойство WaitHandle).
- OperationCanceledException — исключение, выброс которого по соглашению означает, что запрос на отмену операции был обработан и операция должна считаться отменённой. Предпочтительный способ генерации исключения — вызов метода CancellationToken. ThrowIfCancellationRequested.
Механизм отмены через CancellationToken является стандартным для TPL — есть перегрузки методов, принимающих CancellationToken, исключения OperationCanceledException специальным образом обрабатываются и т.д. Однако, как и в любом другом API, есть свои тонкости, хитрости, best practices.
Почему отмена кооперативная?
- Код, выполняющий асинхронную операцию, можно условно поделить на три части (слоя):
- Код «вокруг» асинхронной операции, внешний слой. Этот код инициирует операцию, обрабатывает её результат и исключения, возникшие при выполнении операции.
- Код «внутри» асинхронной операции, внутренний слой. Этот код реализует саму операцию, выполняет полезную нагрузку — расчёты, ввод/вывод, обработку данных и т.п.
- Код-посредник между внешним (1) и внутренним (2) кодом, инфраструктурный слой. Он отвечает за низкоуровневые детали — запускает операцию на выполнение в нужном потоке, публикует результат выполнения операции, чтобы он был доступен внешнему коду и т.д. В случае использования TPL этот код находится внутри самой TPL.
Read more: Habrahabr.ru
QR:
0 comments:
Post a Comment