缓冲流 - ASP.NET Core 3.0 中不允许同步操作
Buffered Stream - Synchronous operations are disallowed in ASP.NET Core 3.0
我有一个针对 AspNetCore 2.2 的 REST 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:
上创建了我想要 return 的 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);
}
}
}
现在我得到这个异常:"Synchronous operations are disallowed in ASP.NET Core 3.0"
如何在不使用 AllowSynchronousIO = true; 的情况下更改此代码以使其正常工作?
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 disabled in all servers
通过在退出 using 子句之前调用 FlushAsync 和 DisposeAsync,您可以停止在 writer 处置期间发生的同步操作。 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
我有一个针对 AspNetCore 2.2 的 REST 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:
上创建了我想要 return 的 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);
}
}
}
现在我得到这个异常:"Synchronous operations are disallowed in ASP.NET Core 3.0" 如何在不使用 AllowSynchronousIO = true; 的情况下更改此代码以使其正常工作?
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 disabled in all servers
通过在退出 using 子句之前调用 FlushAsync 和 DisposeAsync,您可以停止在 writer 处置期间发生的同步操作。 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