![](/img/trans.png)
[英]Do I need to synchronize resource access between Tasks with the default TaskScheduler?
[英]Http.IMiddleware Do not create tasks without passing a TaskScheduler
(.Net 3.1,Visual Studio 2019)
在 DevExpress 代码示例: https://github.com/DevExpress-Examples/blazor-server-dxdatagrid-export/blob/19.2.2%2B/CS/DxDataGridExportingWithReports/Helpers/ExportMiddleware.cs中,得到了以下 http 中间件代码的警告
不要在没有通过 TaskScheduler 的情况下创建任务...
重写代码以启动新任务的正确方法是什么?
public class ExportMiddleware : IMiddleware
{
......
public Task InvokeAsync(HttpContext context, RequestDelegate next)
{
......
_ = await new TaskFactory().StartNew(() => // warning: Do not create tasks without passing a TaskScheduler
{
report.CreateDocument();
using (MemoryStream fs = new MemoryStream())
{
if (format == pdf)
report.ExportToPdf(fs);
else if (format == xlsx)
report.ExportToXlsx(fs);
else if (format == docx)
report.ExportToDocx(fs);
context.Response.Clear();
context.Response.Headers.Append("Content-Type", "application/" + format);
context.Response.Headers.Append("Content-Transfer-Encoding", "binary");
context.Response.Headers.Append("Content-Disposition", "attachment; filename=ExportedDocument." + format);
context.Response.Body.WriteAsync(fs.ToArray(), 0, fs.ToArray().Length);
return context.Response.CompleteAsync();
}
});
从技术上讲,要回答实际问题,代码应该使用Task.Run
而不是StartNew
:
_ = Task.Run(() =>
然而,这是一个非常糟糕的主意。 这不仅是fire-and-forget ,它会在将来的某个随机时间使用context.Response
。 它将开始写入响应 stream,然后在写入完成之前完成 stream。 它完全坏了。
我认为更合适的解决方案是完全删除工厂/启动/运行并在必要时使用await
:
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
......
report.CreateDocument();
using (MemoryStream fs = new MemoryStream())
{
if (format == pdf)
report.ExportToPdf(fs);
else if (format == xlsx)
report.ExportToXlsx(fs);
else if (format == docx)
report.ExportToDocx(fs);
context.Response.Clear();
context.Response.Headers.Append("Content-Type", "application/" + format);
context.Response.Headers.Append("Content-Transfer-Encoding", "binary");
context.Response.Headers.Append("Content-Disposition", "attachment; filename=ExportedDocument." + format);
await context.Response.Body.WriteAsync(fs.ToArray(), 0, fs.ToArray().Length);
await context.Response.CompleteAsync();
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.