TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.78K subscribers
Post #1249 1.44K
День 1021. #ЗаметкиНаПолях #AsyncTips
Потребление ValueTask
Когда Использовать ValueTask

Задача
Требуется организовать потребление ValueTask<T>.

Решение
В большинстве случаев все, что необходимо сделать – добавить await:
ValueTask<int> MethodAsync();
…
int value = await MethodAsync();

Также можно выполнить await после выполнения конкурентной операции, как в случае с Task<T>:
ValueTask<int> valueTask = MethodAsync();
// Другая параллельная работа.
int value = await valueTask;

Однако следует помнить, что ValueTask или ValueTask<T> может ожидаться только один раз.

Чтобы сделать что-то более сложное, преобразуйте ValueTask<T> в Task<T> вызовом AsTask:
Task<int> task = MethodAsync().AsTask();
// Другая параллельная работа.
int value = await task;
int anotherValue = await task;
Многократное ожидание Task<T> абсолютно безопасно.

Также возможны другие операции, например, асинхронное ожидание завершения нескольких операций:
Task<int> task1 = MethodAsync().AsTask();
Task<int> task2 = MethodAsync().AsTask();

int[] results = await Task.WhenAll(task1, task2);

Тем не менее для каждого ValueTask<T> можно вызвать AsTask только один раз. Также вы не можете одновременно использовать await и вызвать AsTask для одного ValueTask<T>.

Другие свойства ValueTask<T> предназначены для нетривиального использования. Обычно они работают не так, как другие известные свойства. В частности, для ValueTask<T>.Result действуют более жёсткие ограничения, чем для Task<T>.Result. Код, который синхронно получает результат от ValueTask<T>, может вызвать ValueTask<T>.Result или ValueTask<T>. GetAwaiter().GetResult(), но эти компоненты не должны вызываться до завершения ValueTask<T>. Синхронная загрузка результата из Task<T> блокирует вызывающий поток до завершения задачи; ValueTask<T> таких гарантий не даёт. Синхронное получение результатов от ValueTask или ValueTask<T> может быть выполнено только один раз, после завершения ValueTask, и это значение ValueTask уже не может использоваться для ожидания или преобразования в задачу. В противном случае вы получите непредсказуемый результат операции.

Итого
Когда ваш код вызывает метод, возвращающий ValueTask или ValueTask<T>, он должен либо немедленно выполнить await для этого ValueTask, либо немедленно вызвать AsTask для преобразования в Task. Возможно, эта простая рекомендация не исчерпывает все нетривиальные сценарии, но большинству приложений этого будет вполне достаточно.

Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 2.
  • 👍 3
More from @netdeveloperdiary
  1. Oct 17, 2026День 2817. #ЧтоНовенького #VS Прекращаем Сборку После Первой Ошибки Мэдс Кристенсен продол…
  2. Oct 16, 2026День 2816. #Карьера #AI Станет ли ИИ-Кодинг Концом Программирования для Людей? Автор ориги…
  3. Oct 15, 2026Post #3374
  4. Oct 14, 2026Post #3373
  5. Oct 13, 2026День 2813. #ЗаметкиНаПолях #Async Ещё Раз Про Async/Await в C#. Часть 1 Почему существует…
  6. Oct 12, 2026День 2812. #Карьера #AI Как Разработчикам Оставаться Полезными, Когда Код Пишет ИИ? По мер…
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 →