2013-07-10 157 views
11

这是我的问题:我需要在ApiController中调用多个第三方方法。这些方法的签名是Task DoSomethingAsync(SomeClass someData, SomeOtherClass moreData)。我希望这些调用在ApiController将数据发送回客户端后在后台继续运行。当DoSomethingAsync完成时,我想做一些日志记录,也许将一些数据保存到文件系统。我怎样才能做到这一点?我宁愿使用asyny/await语法。WebAPI中的长时间运行任务

+0

你的任务有类似'.ContinueWith'。这是你可以做记录的地方。 –

+0

当你说“在ApiController将数据发送回客户端之后”时,你的意思是说该连接也关闭了吗?客户端是否可以在保持连接打开的同时从服务器接收数据? –

+0

是的,连接已关闭。 – TEst16

回答

7

Stephen介绍了为什么要在ApiController中启动基本上长时间运行的“即燃即用”任务是一个坏主意。

也许你应该创建一个单独的服务来执行那些“即丢即忘”的任务。 服务可能是一个不同的ApiController,队列后面的工作者,任何可以独立托管并具有独立生命周期的东西。

这将使不同任务生命周期的管理变得更容易,并将长时间运行的任务与ApiController的核心职责分开。

+1

为什么最好有一个单独的服务的另一个原因是使其更容易扩展。例如,也许你发现你需要更多的服务器来运行长时间运行的任务,但没有更多的服务器来运行你的网站。通过在开始时分解这些,您可以更好地定制您的扩展解决方案。 – jt000

16

你几乎从不想这样做。这几乎总是一个很大的错误。

ASP.NET(以及大多数其他服务器)的工作原理是,一旦完成所有请求,就可以安全地拆除您的服务。所以你有没有保证你的日志将被完成,或者你的数据将被写入磁盘。特别是对于磁盘写入,写入操作完全可能会损坏。

这就是说,如果你是绝对相信,要实现这个极其危险设计,您可以使用BackgroundTaskManager from my blog

+1

在Azure-WebJobs之前更正。现在你可以用Azure-WebJobs来做到这一点。工人角色是最稳健的方法。 – RickAndMSFT

+0

我发现这是一个可以接受的交易,例如:调试日志记录,性能记录,事件跟踪(使用外部服务)。在所有这些情况下,“即丢即用”的语义是可以接受的,我们并不在乎在服务拆除的情况下单个事件是否会丢失。还是有我失踪的东西? –

+0

@JohannesRudolph:我想说的主要用例是缓存更新。如果您接受日志可能不包含所有数据,那么这是一种可接受的日志记录方式。我会将“事件跟踪”解释为业务需求,因此不是一个很好的用例。如果“事件跟踪”不重要,那么“调试日志记录”,“性能记录”和“事件跟踪”只是三种不同的日志记录。请注意,ASP.NET 4.5.2现在具有类似的内置内容。 –

16

好消息,有在.NET 4.5.2叫QueueBackgroundWorkItem一个新的解决方案API。它的使用非常简单:

HostingEnvironment.QueueBackgroundWorkItem(ct => DoSomething(a, b, c)); 

这里有一篇文章详细描述它。

https://blogs.msdn.microsoft.com/webdev/2014/06/04/queuebackgroundworkitem-to-reliably-schedule-and-run-background-processes-in-asp-net/

而这里的anohter一篇文章,提到在这个线程未提及的其他一些方法。 http://www.hanselman.com/blog/HowToRunBackgroundTasksInASPNET.aspx

+3

如果长时间运行的任务不是真正的长时间运行,也就是说它可以在不到90秒的时间内完成,QueueBackgroundWorkItem可以是一个解决方案。如果真的需要长时间运行,则需要另一种解决方案(如将它交给Windows服务) –

+0

我无法在Windows服务(后端数据层)内的自托管WebAPI中使用此工具。 –