Буферизованный поток - синхронные операции запрещены в ASP. NET Core 3.0 - PullRequest
3 голосов
/ 02 апреля 2020

У меня был REST API для AspNetCore 2.2 с конечной точкой, которая позволяет загружать некоторые большие json файлы. После миграции на AspNetCore 3.1 этот код перестал работать:

    try
    {
        HttpContext.Response.StatusCode = (int)HttpStatusCode.OK;
        HttpContext.Response.Headers.Add("Content-Type", "application/json");

        using (var bufferedOutput = new BufferedStream(HttpContext.Response.Body, bufferSize: 4 * 1024 * 1024))
        {
            await _downloadService.Download(_applicationId, bufferedOutput);
        }
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, ex.Message);                
    }

Это метод загрузки, который создал json, который я хочу вернуть на HttpContext.Response.Body:

    public async Task Download(string applicationId, Stream output, CancellationToken cancellationToken = default(CancellationToken))
    {       
        using (var textWriter = new StreamWriter(output, Constants.Utf8))
        {
            using (var jsonWriter = new JsonTextWriter(textWriter))
            {
                jsonWriter.Formatting = Formatting.None;
                await jsonWriter.WriteStartArrayAsync(cancellationToken);

                //write json...
                await jsonWriter.WritePropertyNameAsync("Status", cancellationToken);
                await jsonWriter.WriteValueAsync(someStatus, cancellationToken); 

                await jsonWriter.WriteEndArrayAsync(cancellationToken);
            }
        }
    }

Теперь я получаю это исключение: «Синхронные операции запрещены в ASP. NET Core 3.0» Как я могу изменить этот код для работы без использования AllowSynchronousIO = true;

Ответы [ 2 ]

1 голос
/ 02 апреля 2020

Вызывая FlushAsyn c и DisposeAsyn c перед выходом из условия использования, вы можете остановить синхронные операции, которые происходят во время расположения записи. BufferedStream, кажется, имеет проблему синхронной записи, как насчет управления размером буфера в StreamWriter.

using (var streamWriter = new StreamWriter(context.Response.Body, Encoding.UTF8, 1024))
using (var jsonWriter = new JsonTextWriter(streamWriter))
{
    jsonWriter.Formatting = Formatting.None;
    await jsonWriter.WriteStartObjectAsync();
    await jsonWriter.WritePropertyNameAsync("test");
    await jsonWriter.WriteValueAsync("value " + new string('a', 1024 * 65));
    await jsonWriter.WriteEndObjectAsync();

    await jsonWriter.FlushAsync();
    await streamWriter.FlushAsync();
    await streamWriter.DisposeAsync();
}

Таким образом, вы можете заставить свой код работать с небольшим изменением без AllowSynchronousIO = true

1 голос
/ 02 апреля 2020
Опция

AllowSynchronousIO по умолчанию отключена из .Net core 3.0.0-preview3 in (Kestrel, HttpSys, IIS in-process, TestServer), потому что эти API являются источником истощения потока и зависания приложения.

Параметр может быть переопределен для каждого запроса на временную миграцию:

var allowSynchronousIoOption = HttpContext.Features.Get<IHttpBodyControlFeature>();
if (allowSynchronousIoOption != null)
{
    allowSynchronousIoOption.AllowSynchronousIO = true;
}

Вы можете найти дополнительную информацию и следить за ASP. NET Базовым средством отслеживания проблем: AllowSynchronousIO отключен во всех серверы

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...