Асинхронность в Рантайме в превью 1 .NET 11. Начало
В .NET 11 превью 1 появилась революционная функция: асинхронные операции в среде выполнения. Вместо того чтобы заставлять компилятор C# переписывать методы async/await в конечные автоматы, сама среда выполнения .NET теперь будет рассматривать асинхронные методы как нативную концепцию. Рассмотрим, что это такое, почему это важно и как вы можете поэкспериментировать с ними.
Проблема с текущей реализацией
С тех пор, как в C# 5 были введены async/await, компилятор был единственным ответственным за работу асинхронных операций. Когда вы пишете асинхронный метод, компилятор C# переписывает его в конечный автомат — сгенерированную структуру, реализующую IAsyncStateMachine, которая отслеживает прогресс метода в точках приостановки.
Недостатки
1. Накладные расходы на конечный автомат
Каждый асинхронный метод генерирует структуру конечного автомата с полями для каждой локальной переменной, которая «переходит через await». Когда метод не завершается синхронно, эта структура помещается в кучу.
2. Неудобство для отладчика
Сгенерированный код конечного автомата затрудняет пошаговое выполнение асинхронных методов. Трассировка стека показывает синтетические методы MoveNext вместо исходных имён методов.
3. Слепые зоны профилировщика
Инструменты анализа производительности с трудом правильно распределяют время между точками приостановки асинхронных операций, поскольку среда выполнения не знает асинхронной семантики — она видит только обычные вызовы методов.
4. Упущенные возможности оптимизации
Т.к. среда выполнения не понимает паттерн асинхронности, она не может оптимизировать цепочки асинхронных вызовов. Каждый вызов await приводит к полному циклу приостановки/возобновления, даже если среда выполнения теоретически могла бы оптимизировать передачу управления.
Что такое асинхронность в среде выполнения?
Асинхронность в среде выполнения переносит понятие асинхронных методов из компилятора в саму среду выполнения .NET. Вместо того чтобы компилятор генерировал сложный конечный автомат, он генерирует более простой IL-код, аннотированный
[MethodImpl(MethodImplOptions.Async)]. Затем среда выполнения берёт на себя ответственность за:- Приостановление и возобновление: среда выполнения управляет сохранением и восстановлением состояния метода в точках приостановки, устраняя необходимость в структурах конечного автомата, генерируемых компилятором.
- Поднятие локальных переменных: «Поднимаются» (сохраняются при переходе через await) только те переменные, которые фактически существуют между точками приостановки, и среда выполнения обрабатывает это напрямую.
- Оптимизированные асинхронные вызовы: когда один асинхронный метод среды выполнения вызывает другой, среда выполнения может оптимизировать передачу, потенциально полностью избегая аллокаций экземпляров Task в цепочках асинхронных вызовов.
Как работает новая модель?
В модели асинхронности в среде выполнения асинхронные методы используют AsyncHelpers для выражения приостановки:
namespace System.Runtime.CompilerServices
{
public static class AsyncHelpers
{
[MethodImpl(MethodImplOptions.Async)]
public static void Await(Task task);
[MethodImpl(MethodImplOptions.Async)]
public static void Await(ValueTask task);
…
}
}
Когда компилятор C# генерирует асинхронный IL-код, вместо построения полного конечного автомата он создает вызов
AsyncHelpers.Await(…). Среда выполнения перехватывает этот вызов, и, если задача ещё не завершена, приостанавливает выполнение метода, сохраняя только необходимое состояние, и возобновляет его позже, когда результат станет доступен.Окончание следует…
Источник: https://laurentkempe.com/2026/02/14/exploring-net-11-preview-1-runtime-async-a-dive-into-the-future-of-async-in-net/
