这是我的问题:我需要在 ApiController 中调用多个第 3 方方法。这些方法的签名是Task DoSomethingAsync(SomeClass someData, SomeOtherClass moreData)
. 在 ApiController 将数据发送回客户端之后,我希望这些调用继续在后台运行。完成DoSomethingAsync
后,我想做一些日志记录,并可能将一些数据保存到文件系统中。我怎样才能做到这一点?我更喜欢使用 asyny/await 语法。
5 回答
好消息,.NET 4.5.2 中有一个名为 QueueBackgroundWorkItem API 的新解决方案。使用起来非常简单:
HostingEnvironment.QueueBackgroundWorkItem(ct => DoSomething(a, b, c));
这是一篇详细描述它的文章。
这是另一篇文章,其中提到了该线程中未提及的其他一些方法。 http://www.hanselman.com/blog/HowToRunBackgroundTasksInASPNET.aspx
你几乎从不想这样做。这几乎总是一个大错误。
ASP.NET(和大多数其他服务器)的工作假设是,一旦所有请求完成,就可以安全地关闭您的服务。所以你不能保证你的日志记录会完成,或者你的数据会被写入磁盘。特别是对于磁盘写入,您的写入完全有可能被破坏。
也就是说,如果您绝对确定要实施这种极其危险的设计,您可以使用BackgroundTaskManager
我博客中的。
更新:我写了一个博客系列,详细介绍了request-extrinsic code 的正确解决方案。总之,您真正想做的是将请求外部代码移出 ASP.NET。引入持久队列和独立处理器;ASP.NET 控制器操作会将请求放入队列,独立处理器将读取请求并执行它们。这个“处理器”可以是 Azure Function/WebJob、Win32 Service 等。
Stephen 描述了为什么在 ApiController 中启动基本上长时间运行的即发即弃任务是一个坏主意。
也许您应该创建一个单独的服务来执行那些即发即弃的任务。该服务可以是不同的 ApiController、队列后面的工作人员、可以独立托管并具有独立生命周期的任何内容。
这将使不同任务生命周期的管理变得更加容易,并将长期运行的任务的关注点与 ApiController 的核心职责分开。
正如其他人指出的那样,不建议这样做。但是,只要有需要就有办法,所以看看IRegisteredObject
也可以看看
尽管这个问题已经存在好几年了,但现在最好的解决方案是在这种情况下使用 Singal R。