缓冲流-ASP.NET Core 3.0中不允许同步操作

问题描述 投票:2回答:2

我有一个针对AspNetCore 2.2的REST API,该API的端点允许下载一些大的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);                
    }

这是下载方法,它创建了我想在HttpContext.Response.Body上返回的json:

    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的情况下更改此代码以使其工作?

c# asp.net-core asynchronous core asp.net-core-3.1
2个回答
1
投票

[AllowSynchronousIO选项默认情况下是从[.Net core 3.0.0-preview3KestrelHttpSysIIS in-process)中的TestServer禁用的,因为这些API是线程饥饿和应用程序挂起的源。

对于临时迁移,每个请求都可以覆盖该选项:

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

您可以找到更多信息并关注ASP.NET Core问题跟踪器:AllowSynchronousIO disabled in all servers


0
投票

通过退出using子句之前调用FlushAsync和DisposeAsync,您可以停止在编写器处置期间发生的同步操作。 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的情况下进行少量更改就可以工作代码>

© www.soinside.com 2019 - 2024. All rights reserved.