Разъяснение того, как IAsyncEnumerable работает с ASP.NET Web API

9

Я столкнулся с интересным поведением при изучении IAsyncEnumerable в проекте ASP.NET Web API. Рассмотрим следующие примеры кода:

    // Code Sample 1
    [HttpGet]
    public async IAsyncEnumerable<int> GetAsync()
    {
        for (int i = 0; i < 10; i++)
        {
            await Task.Delay(1000);
            yield return i;
        }
    }


    // Code Sample 2
    [HttpGet]
    public async IAsyncEnumerable<string> GetAsync()
    {
        for (int i = 0; i < 10; i++)
        {
            await Task.Delay(1000);
            yield return i.ToString();
        }
    }

Образец 1 (массив int) возвращается {}как результат JSON.

Образец 2 возвращает ожидаемый результат ["0","1","2","3","4","5","6","7","8","9"]. Однако весь массив JSON возвращается сразу после 10 секунд ожидания. Разве это не должно быть возвращено, поскольку данные становятся доступными, как и ожидалось от интерфейса IAsyncEnumerable? Или есть какой-то конкретный способ использования этого веб-API?

Рави М Патель
источник
4
Разве это не должно быть возвращено, поскольку данные становятся доступными, как и ожидалось от интерфейса IAsyncEnumerable? ... и это делает ... но JSon сериализатором
Selvin
1
и пример 1 .... похоже на ошибку для не ссылочного типа (если вы измените IAsyncEnumerable<int>на IAsyncEnumerable<object>- это должно работать, но тогда будет задействован бокс)
Selvin
@ Селвин, не могли бы вы уточнить? Или указать на пример кода? Я пытался использовать этот API с клиентом C #, результат тот же, нужно подождать 10 секунд ...
Рави М Патель
придется подождать 10 секунд, это obviosu ... сериализация на стороне сервера, и это не асинхронно ... подробно о чем?
Сельвин

Ответы:

3

Вызов веб-API не будет возвращать частичный JSON каждую секунду. Сериализатору json приходится ждать 10x1секунду (или код, вызывающий сериализатор json, который является частью ASP .NET). После того как код инфраструктуры и сериализатор получат все данные, они будут сериализованы и переданы клиенту в виде одного ответа.

В возвращаемых типах действий контроллера в веб-API ASP.NET Core мы можем прочитать:

В ASP.NET Core 3.0 и более поздних версиях возвращая IAsyncEnumerable из действия:

  • Больше не приводит к синхронной итерации.
  • Становится так же эффективно, как и возврат IEnumerable.

ASP.NET Core 3.0 и более поздних версий буферизует результат следующего действия перед его передачей в сериализатор:

public IEnumerable<Product> GetOnSaleProducts() =>
  _context.Products.Where(p => p.IsOnSale);
tymtam
источник