TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.75K subscribers
Post #2585 2.51K
День 2137. #Оффтоп
async2 — Завершение Эксперимента с Асинхронностью в .NET. Окончание

Начало

async — функция компилятора
Текущая реализация async и await — это функция компилятора. Компилятор генерирует конечный автомат для async -метода. Среда выполнения ничего не знает об async и await. Нет никаких следов ключевого слова async в IL или в JIT-скомпилированном коде. И вот с этого начался эксперимент, подробно описанный здесь.

async — функция среды выполнения
Целью эксперимента было переместить async и await в среду выполнения. Это позволило бы среде выполнения иметь больше контроля над самим шаблоном. При этом также была бы другая семантика.

async2 не сохраняет и не восстанавливает контекст синхронизации и контекст исполнения на границах функций, вместо этого позволяя вызывающим методам наблюдать изменения. С ExecutionContext это изменяет поведение AsyncLocal.

Сегодня AsyncLocal используется для хранения данных, которые передаются с логическим контекстом вызова. Они копируются в новый контекст. Тем не менее, если функция глубоко в стеке вызовов изменяет значение AsyncLocal, вызывающий метод не увидит обновлённое значение, его увидят только методы ниже по логическому асинхронному потоку. Например:
await new AsyncLocalTest().Outer();

public class AsyncLocalTest
{
private readonly AsyncLocal<string>
_al = new();

public async Task Outer()
{
_al.Value = "Out";
Console.WriteLine($"Outer: {_al.Value}");
await Inner();
Console.WriteLine($"Outer: {_al.Value}");
}

private async Task Inner()
{
_al.Value = "In";
Console.WriteLine($"Inner: {_al.Value}");
await Task.Yield();
Console.WriteLine($"Inner: {_al.Value}");
}
}

Вывод:
Outer: Out
Inner: In
Inner: In
Outer: Out

В async2 изменения не «откатываются», что приводит к другому выводу:
Outer: Out
Inner: In
Inner: In
Outer: In


Сравнение с текущей реализацией
Команда обнаружила, что подход с помещением асинхронности в JIT может дать наилучшие результаты в целом. Вот основные отличия:
1. Производительность
Async обычно медленнее, чем async2, особенно для глубоких стеков вызовов, где async2 имеет производительность, сопоставимую с синхронным кодом в сценариях без приостановки исполнения.
2. Обработка исключений
В async медленно и неэффективно, вызывает паузы GC и влияет на отзывчивость приложений. В async2 улучшена.
3. Ограничение глубины стека
Присутствует в async, что может вызвать проблемы для глубоких стеков вызовов. Нет явных ограничений в async2.
4. Потребление памяти
В async обычно ниже, особенно в сценариях с большим количеством приостановленных задач. В async2 более высокое потребление памяти из-за захвата целых стековых кадров и регистров, но все ещё приемлемо по сравнению с другими факторами, такими как время паузы.

Полный документ здесь.

Что дальше?
Пока это всего лишь эксперимент, который может привести к замене async через несколько лет. Да, может пройти некоторое время, прежде чем это будет выпущено. А для переходной фазы должен быть interop для async <-> async2. В любом случае - очень хорошая отправная точка. Ждём async2, как юнионов.

Источник: https://steven-giesel.com/blogPost/59752c38-9c99-4641-9853-9cfa97bb2d29/async2-the-net-runtime-async-experiment-concludes
  • 👍 20
More from @netdeveloperdiary
  1. Oct 6, 2026🦈 Открытое собеседование на Middle C# | 6 октября, 19:00 МСК Приглашаем на открытое собес…
  2. Oct 6, 2026День 2806. #ЗаметкиНаПолях Типы Коллекций в .NET, Которые Стоит Попробовать. Начало Больши…
  3. Oct 5, 2026День 2805. #ЧтоНовенького #NET11 Аргументы в Выражениях Коллекций в C#15 В C#15 реализован…
  4. Oct 4, 2026День 2804. #ВопросыНаСобеседовании Марк Прайс предложил свой набор из 60 вопросов (как тех…
  5. Oct 3, 2026Post #3360
  6. Oct 3, 2026День 2803. #Оффтоп Чем Заняться, Пока Работают Агенты? У VS Code Есть Ответ Сейчас большую…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →