Поток событий — на стороне сервера
В этом посте мы собираемся изучить способ потоковой передачи данных клиенту с помощью веб-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();
}
}
Когда конечная точка вызывается, она отправляет новую «строку» данных вместо ожидания одновременной отправки всех элементов, которые будут обработаны.
Только полноправные пользователи могут оставлять комментарии. Аутентифицируйтесь пожалуйста, используя сервисы.