ASP.NET核心服务器,AllowSynchronousIO设置为false
new WebHostBuilder()
.UseKestrel(options =>
{
options.AllowSynchronousIO = false;
})
Run Code Online (Sandbox Code Playgroud)
在动作中,它输出一个JsonResult
public async Task<IActionResult> SanityCheck()
{
Dictionary<string, string> dic = await GetDic();
return this.Json(dic);
}
Run Code Online (Sandbox Code Playgroud)
它以一个异常结束
System.InvalidOperationException:不允许进行同步操作。调用WriteAsync或将AllowSynchronousIO设置为true。
我不能用返回JsonResult AllowSynchronousIO=false吗?
最好的祝福
Joh*_*ica 37
我设法使用以下中间件(.NET 6.0)找到了这个问题的我自己的独特版本:
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
context.Response.StatusCode = 200;
using (var writer = new StreamWriter(context.Response.Body))
{
await writer.WriteLineAsync("Done!");
return;
}
}
Run Code Online (Sandbox Code Playgroud)
我花了很长时间盯着这个,直到我意识到堆栈跟踪告诉我什么:
System.InvalidOperationException:不允许同步操作。改为调用 WriteAsync 或将 AllowSynchronousIO 设置为 true。
在 Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpResponseStream.Write(Byte[] 缓冲区,Int32 偏移量,Int32 计数)
在 System.IO.Stream.Write(ReadOnlySpan`1 缓冲区)
在System.IO.StreamWriter.Flush(布尔flushStream,布尔flushEncoder)
在 System.IO.StreamWriter.Dispose(布尔处置)
在 System.IO.TextWriter.Dispose()
这里重要的一行是System.IO.TextWriter.Dispose():这导致同步调用生成的刷新和较低级别的写入。
幸运的是,StreamWriter实现了,所以很容易通过添加beforeIAsyncDisposable来解决它:awaitusing
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
context.Response.StatusCode = 200;
await using (var writer = new StreamWriter(context.Response.Body))
{
await writer.WriteLineAsync("Done!");
return;
}
}
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助别人不要像我一样浪费太多时间。
小智 22
您可能遇到以下问题:https : //github.com/aspnet/AspNetCore/issues/8302
您可以在这里找到更多信息:https : //github.com/aspnet/AspNetCore/issues/7644
解决问题之前的解决方法是允许同步IO。将其放入用于Kestrel或IIS的Startup.cs中:
public void ConfigureServices(IServiceCollection services)
{
// If using Kestrel:
services.Configure<KestrelServerOptions>(options =>
{
options.AllowSynchronousIO = true;
});
// If using IIS:
services.Configure<IISServerOptions>(options =>
{
options.AllowSynchronousIO = true;
});
}
Run Code Online (Sandbox Code Playgroud)
T-m*_*oty 11
根据Mark Lagendijk的回答,我通过属性以声明方式应用了该逻辑:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class AllowSynchronousIOAttribute : ActionFilterAttribute
{
public AllowSynchronousIOAttribute()
{
}
public override void OnResultExecuting(ResultExecutingContext context)
{
var syncIOFeature = context.HttpContext.Features.Get<IHttpBodyControlFeature>();
if (syncIOFeature != null)
{
syncIOFeature.AllowSynchronousIO = true;
}
}
}
Run Code Online (Sandbox Code Playgroud)
只需在操作方法或整个控制器上使用它即可启用它:
[AllowSynchronousIO]
public IActionResult DownloadSynchronous()
{
return Something();
}
Run Code Online (Sandbox Code Playgroud)
小智 8
我的单元测试有这个问题。我不得不将我的 TestServer 更新为 AlloSynchronousIO
Server = new TestServer(new WebHostBuilder().UseStartup<Startup>());
Server.AllowSynchronousIO = true;
Run Code Online (Sandbox Code Playgroud)
小智 6
在配置服务中添加以下代码。这对我有用
services.Configure<KestrelServerOptions>(options =>
{
options.AllowSynchronousIO = true;
});
// If using IIS:
services.Configure<IISServerOptions>(options =>
{
options.AllowSynchronousIO = true;
});
Run Code Online (Sandbox Code Playgroud)
当异常在您无法控制的代码中抛出时,除了启用之外别无选择AllowSynchronousIO,最好为特定请求启用它,而不是全局启用它。
在宣布此功能的GitHub 问题中,建议使用以下解决方法:
var syncIOFeature = HttpContext.Features.Get<IHttpBodyControlFeature>();
if (syncIOFeature != null)
{
syncIOFeature.AllowSynchronousIO = true;
}
Run Code Online (Sandbox Code Playgroud)
您可以创建一个简单的中间件函数来将其应用于特定请求:
app.Use(app.Use(async (context, next) =>
{
if (context.Request.Path.StartsWithSegments("/some-endpoint-that-needs-sync-io"))
{
var syncIoFeature = context.Features.Get<IHttpBodyControlFeature>();
if (syncIoFeature != null)
{
syncIoFeature.AllowSynchronousIO = true;
}
}
await next();
})
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5335 次 |
| 最近记录: |