Поток событий — на стороне сервера

  • Михаил
  • 12 мин. на прочтение
  • 118
  • 19 Dec 2020
  • 19 Dec 2022

В этом посте мы собираемся изучить способ потоковой передачи данных клиенту с помощью веб-API и C#.

Представьте себе это требование: вам нужно обработать массив данных, скажем, 100 элементов, после обработки каждого элемента API должен возвращать данные клиенту без SignalR.

Для этого в этом примере у нас будет рабочий процесс, который будет возвращать IAsyncEnumerable и между каждой итерацией метод будет ждать от 5 до 10 секунд.       

//Service.cs
private static readonly Random _random = new Random();

public async IAsyncEnumerable<int> GetData(int amount)
{
    foreach(var item in Enumerable.Range(0, amount))
    {
        // Wait a random amount of time to simulate some work.
        var secondsToWait = _random.Next(5,10);
        await Task.Delay(TimeSpan.FromSeconds(secondsToWait));
        yield return item;
    }
}        

Создав смоделированный сервис, мы можем перейти к Controller. Для конечной точки у нас будет async Task Getметод, который будет записывать результат в Response и отправлять его для каждого обработанного элемента.  
   

// HomeController.cs
private readonly IService service;

public HomeController(IService service)
{
    this.service = service;
}

[HttpGet("5/{amount:int:min(1)}")]
public async Task GetStreamData(int amount)
{
    // Set Content-Type to text/event-stream
    Response.Headers.Add("Content-Type", "text/event-stream");

    await foreach(var data in service.GetData(amount))
    {
        // this can be anything, even just a json object
        string dataItem = $"data: {data}\n\n";

        // Convert the text to a byte array
        var utf8DataitemBytes = Encoding.UTF8.GetBytes(dataItem);

        // Write the byte array to the HttpResponse
        await Response.Body.WriteAsync(utf8DataitemBytes, 0, utf8DataitemBytes.Length);
        // Push
        await Response.Body.FlushAsync();
    }
}

Когда конечная точка вызывается, она отправляет новую «строку» данных вместо ожидания одновременной отправки всех элементов, которые будут обработаны.