C# 不在Web API控制器中等待任务可以吗

C# 不在Web API控制器中等待任务可以吗,c#,asp.net-web-api,async-await,C#,Asp.net Web Api,Async Await,所以我遇到了一些让我感到不舒服的代码,但我找不到一个确切的答案,它是否真的有问题 我们有一个ASP.NETWebAPI,主要由消息总线使用。需要为多个账户启动一个平衡流程。平衡服务方法是异步的,并返回一个任务。代码的调用方式如下: foreach (AccountingGroup accountingGroup in Groups) { ledgerService.CreateItemsAsync(accountingGroup.GLAccountingHeaderId); } retu

所以我遇到了一些让我感到不舒服的代码,但我找不到一个确切的答案,它是否真的有问题

我们有一个ASP.NETWebAPI,主要由消息总线使用。需要为多个账户启动一个平衡流程。平衡服务方法是异步的,并返回一个任务。代码的调用方式如下:

foreach (AccountingGroup accountingGroup in Groups)
{
    ledgerService.CreateItemsAsync(accountingGroup.GLAccountingHeaderId);
}
return StatusCode(HttpStatusCode.NoContent);
我觉得这在很多方面都是错误的。我明白你的意图。我们希望在所有这些组上运行此方法,但不需要等待它们完成

显然,取消令牌没有被使用。他们依赖于AWS,如果整个过程运行太长的话,他们会终止整个过程,而这不是我现在能真正进入的重构

我已经离开C语言一年半了,异步代码已经2.5年了,我觉得我在某种程度上知道了这个问题,但是我再也找不到了


处理这个问题的正确方法是什么?这是一个问题吗?

正确的方法是将API方法定义为异步,然后等待所有异步方法完成:

public Task<IHttpActionResult> DoStuff()
{
    await Task.WhenAll(groups.Select(g =>
                     ledgerService.CreateItemsAsync(g.GLAccountingHeaderId));
    return StatusCode(HttpStatusCode.NoContent);
}
帕特里克的回答解释了原因。向客户假装一个操作已经完成,而它还没有完成,这似乎是一个坏主意


如果您想在后台运行这些东西,您可以研究使用RabbitMq之类的消息队列,并开发一种确保这些任务完成的故障安全方法。失败时的反馈是好的。使用当前的方法,您完全无法确定此代码是否失败,这意味着如果它停止工作,您将无法意识到,直到它影响到其他内容。

正确的方法是将API方法定义为异步,然后等待所有异步方法完成:

public Task<IHttpActionResult> DoStuff()
{
    await Task.WhenAll(groups.Select(g =>
                     ledgerService.CreateItemsAsync(g.GLAccountingHeaderId));
    return StatusCode(HttpStatusCode.NoContent);
}
帕特里克的回答解释了原因。向客户假装一个操作已经完成,而它还没有完成,这似乎是一个坏主意

如果您想在后台运行这些东西,您可以研究使用RabbitMq之类的消息队列,并开发一种确保这些任务完成的故障安全方法。失败时的反馈是好的。用你目前的方法,你绝对没有办法知道这段代码是否失败,也就是说,如果它停止工作,你将无法意识到,直到它影响到其他东西

这是个问题吗

是的,不想等待和实际上能够处理异常是有区别的

例如,如果您的代码由于任何原因失败,您现在将返回一个HTTP 204,即成功状态。如果您等待结果,但它失败了,那么很可能会得到HTTP 500

处理这个问题的正确方法是什么

您应该等待结果,例如聚合任务并调用Task.whallon,这样您就不必单独等待每个任务

这是个问题吗

是的,不想等待和实际上能够处理异常是有区别的

例如,如果您的代码由于任何原因失败,您现在将返回一个HTTP 204,即成功状态。如果您等待结果,但它失败了,那么很可能会得到HTTP 500

处理这个问题的正确方法是什么


您应该等待结果,例如聚合任务并调用Task.whallon,这样您就不必分别等待每一个任务。

不,不正常,服务器可能会在后台工作运行时关闭应用程序域。处理这一问题的最佳方法是使用库进行后台工作,如

如果您觉得工作将在下一分钟内完成,或者您可以使用短期系统,但是我不确定这是否适用于ASP.NET Core,它是为与以前版本的ASP.NET一起使用而设计的


编辑:找到引用,QueueBackgroundWorkItem确实在ASP.NET Core中不起作用,但确实存在。

否如果不正常,服务器可能会在后台工作运行时关闭应用程序域。处理这一问题的最佳方法是使用库进行后台工作,如

如果您觉得工作将在下一分钟内完成,或者您可以使用短期系统,但是我不确定这是否适用于ASP.NET Core,它是为与以前版本的ASP.NET一起使用而设计的


编辑:找到一个引用,QueueBackgroundWorkItem确实在ASP.NET Core中不起作用,但确实存在。

您可以使用QueueBackgroundWorkItem


请查看

您可以使用QueueBackgroundWorkItem


请看一看

您的异步方法开始时有问题-这是一个无效的异步方法,这不是一个好主意-您的异步方法开始时有问题-这是一个无效的异步方法,这不是一个好主意。假装行动已经完成,而它还没有完成,这似乎是个坏主意。是的
. 假装行动已经完成,而实际上还没有完成,这似乎是一个坏主意。这很有趣,但如果你发出信号表明结果是好的,那么当它还在运行,而你甚至不知道它会好起来的时候,这是危险的。@Patrickhoffman我同意,但作为一名顾问,我认为在尽量减少现有项目的结构变化方面也有一些话要说。核心问题是它真的不应该这样做。但我确实喜欢有一个解决方案,可以在不需要重大结构更改的情况下修复bug。所以,谢谢你,斯科特。@Riplikash这就是重点:它不能解决问题。它隐藏了错误。你不希望发生这种事。让数据库服务器离开一秒钟,看看你的代码在实际失败时如何返回成功。Patrick的观点就是为什么我建议首先使用hangfire,如果你的后台工作失败,它将重试指定的次数,然后将失败记录在管理员可以发现的地方。QueueBackgroundWorkItem和IApplicationLifetime不会为您提供现成的好处。Scott,感谢您提供有关在QueueBackgroundWorkItems、IApplicationLifetime和Hangfire之间进行选择的更多信息。很高兴知道这个建议是从哪里来的@帕特里克·霍夫曼我并不反对,但正如我所说的,在咨询的情况下,当你不能实施正确的解决方案时,我认为找到更好的方法来处理问题是有价值的。您不能总是将接口更改为应用程序,因此即使是不需要您更改应用程序接口和工作流程的部分解决方案也是有价值的。有趣的是,如果您在应用程序仍在运行且您不知道结果是否会好的情况下发出信号,则会很危险。@Patrickhoffman我同意,但作为一名顾问,我认为在尽量减少现有项目的结构变化方面也有一些话要说。核心问题是它真的不应该这样做。但我确实喜欢有一个解决方案,可以在不需要重大结构更改的情况下修复bug。所以,谢谢你,斯科特。@Riplikash这就是重点:它不能解决问题。它隐藏了错误。你不希望发生这种事。让数据库服务器离开一秒钟,看看你的代码在实际失败时如何返回成功。Patrick的观点就是为什么我建议首先使用hangfire,如果你的后台工作失败,它将重试指定的次数,然后将失败记录在管理员可以发现的地方。QueueBackgroundWorkItem和IApplicationLifetime不会为您提供现成的好处。Scott,感谢您提供有关在QueueBackgroundWorkItems、IApplicationLifetime和Hangfire之间进行选择的更多信息。很高兴知道这个建议是从哪里来的@帕特里克·霍夫曼我并不反对,但正如我所说的,在咨询的情况下,当你不能实施正确的解决方案时,我认为找到更好的方法来处理问题是有价值的。您不能总是更改应用程序的接口,因此即使是不需要更改应用程序接口和工作流程的局部解决方案也有价值。