.NET 6: Улучшения в Асинхронности
Из более, чем сотни изменений, предложенных для выпуска в .NET 6 сегодня рассмотрим наиболее существенные, относящиеся к асинхронному программированию.
Новые методы WaitAsync
Хотя в идеале все асинхронные функции подразумевают возможность отмены операции, иногда эта возможность не предоставляется. Для этих случаев в классы
Task и Task<TResult> были добавлены три новых метода WaitAsync:public Task WaitAsync(CancellationToken cancellationToken);Как следует из сигнатуры, эти методы используют отмену по таймауту и/или по токену отмены. Любой из них может использоваться для прекращения ожидания завершения асинхронной операции. Обратите внимание, что это не означает прерывания самой операции. Операция может продолжаться, даже если вызывающий код её больше не ожидает.
public Task WaitAsync(TimeSpan timeout);
public Task WaitAsync(TimeSpan timeout, CancellationToken cancellationToken);
На заметку: Microsoft теперь считает ошибкой значения таймаута в виде целых миллисекунд. В дальнейшем все значения таймаута должны быть выражены исключительно как TimeSpan.
Многоразовый CancellationTokenSource
Когда запускается операция, инициируемая извне, например веб-запрос, часто требуется создать
CancellationTokenSource. Это позволяет обработчику запросов прерываться, если запрашивающая сторона отменяет запрос, разрывается соединение и т. д. Однако в большинстве случаев запрос не отменяется, то есть CancellationTokenSource не используется.Чтобы повысить производительность, предлагается повторно использовать
CancellationTokenSource для новых операций. В настоящее время этого нельзя делать, т.к. нет возможности узнать, какая операция в данный момент удерживает существующий токен. Могут возникать непредсказуемые ошибки, если операция отменяется из-за того, что она использует один токен с другой операцией.Новый метод
CancellationTokenSource.TryReset исправляет это, отключая все старые токены от CancellationTokenSource. Таким образом, любая отмена новой операции не сможет повлиять на предыдущие операции. Старые токены будут существовать, но не смогут получать сообщения от этого CancellationTokenSource.Название
TryReset использовано из-за того, что повторно использовать можно будет только неиспользованный объект CancellationTokenSource. То есть, если на этом объекте уже была вызвана отмена операции, придётся создать новый. Использование будет примерно таким:if (!cts.TryReset())События отмены
cts = new CancellationTokenSource();
Один из способов определить, что была запрошена отмена, - зарегистрировать делегат через
CancellationToken.Register. Он будет выполнен при отмене, либо немедленно, если к моменту регистрации токен уже в состоянии отмены. Иногда этому делегату требуется доступ к используемому токену. Новая перегрузка CancellationToken.Register предложит эту возможность:public CancellationTokenRegistration Register<T>(Action<T, CancellationToken> callback, T state);
public CancellationTokenRegistration UnsafeRegister<T>(Action<T, CancellationToken> callback, T state);
UnsafeRegister отличается тем, что не захватывает контекст исполнения. Источник: https://www.infoq.com/news/2021/04/Net6-Async/