Получение HTTP-потока блокирует рендеринг
Я загружаю поток из WebAPI и пытаюсь запустить код во время чтения потока.
Приведенный ниже код прекрасно работает на стороне сервера Blazor или в консольном приложении. Но на стороне клиента Blazor поток сначала полностью загрузится, прежде чем выполнять какой-либо код... даже просто Console.WriteLine() просто начнет запись в консоль после завершения потока. Я использую последнюю версию.Net Core 3.0 Preview 8...
public async IAsyncEnumerable<SomeClass> GetDataAsync()
{
var serializer = new JsonSerializer();
using (var stream = await Http.GetStreamAsync("https://localhost:44334/api/values/i"))
{
using (var sr = new StreamReader(stream))
using (var jr = new JsonTextReader(sr))
{
while (await jr.ReadAsync()) //<-- Stream is fully download to browser before taking any actions.
{
if (jr.TokenType != JsonToken.StartArray && jr.TokenType != JsonToken.EndArray)
{
Console.WriteLine(jsonReader.LinePosition);
yield return serializer.Deserialize<SomeClass>(jr);
}
};
}
}
}
Я проверил это с помощью WireShark, чтобы подтвердить, что это происходит.
Это по замыслу?
1 ответ
Это по замыслу?
Я предполагаю, что это в настоящее время разработано!
это не будет блокировать просто потому, что шаблон асинхронного / ожидающего поддерживается в Blazor на стороне клиента. Мне кажется, что настоящая проблема связана с HttpClient.GetStreamAsync, поскольку служба HttpClient (клиентская версия Blazor) не является действительным или реальным HttpClient. Он основан на JavaScript Fetch Api ( https://github.com/aspnet/AspNetCore/blob/master/src/Components/Web.JS/src/Services/Http.ts):
responseData = await response.arrayBuffer();
Но если они переключатся на реализацию mono ( https://github.com/aspnet/AspNetCore/issues/10489), потоковая передача будет поддерживаться, если браузер поддерживает это: https://github.com/mono/mono/blob/254d6d37580a70fbb4fa072b0b2b16d2984b3bb5/sdks/wasm/framework/src/WebAssembly.Net.Http/WasmHttpMessageHandler.cs#L171-L173
Вызов arrayBuffer() никогда не вернется из чистого потока. Должен быть реализован другой MessageHandler, основанный на этом примере, но я уверен, что в этом случае недостаточно просто реализовать новый обработчик сообщений.
Надеюсь это поможет...