gpt4 book ai didi

C# Async ApiController 路由问题解决 Task.WhenAny 与 Task.Delay

转载 作者:太空狗 更新时间:2023-10-29 23:36:01 25 4
gpt4 key购买 nike

在我的服务器上,我有一个为用户生成 pdf 的路由。当生成时间超过指定的时间量时,路由应该返回一个已接受的状态代码,并在处理完成后向用户发送一封电子邮件。我遇到的问题是 Task.Delay 没有得到尊重。无论我将 PdfGenerationTimeLimitUntilEmail 设置得有多低,Wait.Any 仍然不会解析,直到 createPdfTask 完成。有趣的是,当生成抛出异常或完成,并且时间超过 Task.Delay 时间时,执行继续返回已接受状态。我怀疑罪魁祸首是死锁情况。

一个相关的问题,我已经仔细阅读过,但无法应用于我的问题: 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);
}

最佳答案

如果 Kevin Gosse 是正确的,那么这里真正的问题是 createPdfFromFooData因此 CeatePdfFile在第一个 await 之前 正在做很多工作: 你可以添加 Task.Yield()人为地强制执行额外的等待,本质上是将其余工作推到相关上下文(或线程池,否则)的工作队列中:

    async Task<Stream> CeatePdfFile()
{
await Task.Yield(); // force asynchronicity
var pdf = await createPdfFromFooData(fooBody);

return await pdfFileToStream(pdf);
}

关于C# Async ApiController 路由问题解决 Task.WhenAny 与 Task.Delay,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54789596/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com