在我的服务器上,有一个路由用于为用户生成PDF文件。当生成时间超过指定的时间限制时,该路由应该返回接受状态码,并在处理完成后向用户发送电子邮件。我遇到的问题是无论我将设置多低,
Task.Delay
仍然没有被执行。有趣的是,当生成抛出异常或完成并且时间超过了限制时,执行过程会继续返回Accepted状态。我怀疑罪魁祸首是死锁情况。我阅读了一个相关的问题,但是还没有能够解决我的问题:C#/.NET 4.5 - Why does "await Task.WhenAny" never return when provided with a Task.Delay in a WPF application's UI thread?有什么明显的问题我忽略了吗?或者我应该知道线程上下文的一些东西吗? [HttpPost]
[Route("foo")]
public async Task<IHttpActionResult> Foo([FromBody] FooBody fooBody)
{
var routeUser = await ValidateUser();
async Task<Stream> CeatePdfFile()
{
var pdf = await createPdfFromFooData(fooBody);
return await pdfFileToStream(pdf);
}
var delay = Task.Delay(PdfGenerationTimeLimitUntilEmail);
var createPdfTask = CeatePdfFile();
var firstTaskResolved = await Task.WhenAny(createPdfTask , delay);
if (firstTaskResolved == createPdfTask)
{
var pdfFileStream = await createPdfTask ;
return new FileActionResult(pdfFileStream);
}
// Creating the PDF can take a long time, so just send an email when it's done
async void SendEmail(CancellationToken token)
{
var pdfFileStreamToEmail = await createPdfTask ;
_emailSender.SendDownloadEmail(routeUser.Email, pdfFileStreanToEmail);
}
HostingEnvironment.QueueBackgroundWorkItem(token => SendEmail(token));
return StatusCode(HttpStatusCode.Accepted);
}
...Async
,其中您将Async
后缀添加到返回Task
(或Task<T>
)的任何方法中。它有助于提高代码的可读性。例如:CreatePdfFileAsync()
和可能的SendMailAsync
。 - IgorcreatePdfFromFooData
在产生结果之前会进行长时间的阻塞操作。尝试使用以下代码:var createPdfTask = Task.Run(() => CeatePdfFile());
- Kevin Gosseasync void
- MVC的同步上下文积极阻止async void
- 如果您尝试使用它,它会抛出异常。 - Marc Gravell