如何在ASP.NET Web API中排队后台任务

时间:2013-02-05 15:19:08

标签: c# asp.net-web-api queue

我有一个webapi,旨在以队列方式处理报告。该应用程序采取的步骤如下:

  • 接收内容
  • 将内容映射到对象并将其放入队列
  • 轮询队列中的待处理项目
  • 一次处理队列中的项目

我正在考虑使用Entity Framework来创建排队项目的数据库,例如:

public class EFBatchItem
{
    [Key]
    public string BatchId { get; set; }
    public DateTime DateCreated { get; set; }
    public DateTime DateCompleted { get; set; }
    public string BatchItem { get; set; }
    public BatchStatus Status { get; set; }
}

我的问题 - 使用NServiceBus,BlockingCollection或ConcurrentQeueue是否有更有效的方法,而不是不断轮询数据库并逐个提取待处理的项目?我之前没有使用过队列。

一种想法是创建一个任务队列,并在一个单独的线程上处理所有挂起的任务。与Most efficient way to process a queue with threads有些相似,但我想确保我走的是最有效的路线。

编辑: 我在这里遇到的一个重要问题是向用户显示进度的最佳方式。一旦用户提交内容,他就会进入新页面,并可以按批次标识符查看状态。 MSMQ是必需的,还是NServiceBus,以便通知用户?这似乎是REquest / Acknowledge / Push范式的一种变体?

4 个答案:

答案 0 :(得分:25)

恕我直言,您的ASP.NET Web API应用程序本身不应该运行这些后台任务。它应该只负责接收请求,将其粘贴到队列中(如您所示)并返回指示接收消息成功或失败的响应。您可以使用各种消息传递系统(例如RabbitMQ)来实现此方法。

至于通知,您有几个选择。您可以拥有一个客户端可以检查处理是否完成的端点。或者,您可以提供客户端可以订阅的流API端点。这样,客户端就不必轮询服务器;服务器可以通知连接的客户端。 ASP.NET Web API有一个很好的方法。以下博客文章解释了如何:

您还可以考虑SignalR此类服务器到客户端通知。

ASP.NET Web API应用程序很难执行后台任务的原因是您有责任让AppDomain保持活动状态。这是一个麻烦,尤其是当您在IIS下托管时。以下博客文章解释了我的意思:

答案 1 :(得分:5)

它是一个NuGet包,它被称为HangFire - https://github.com/HangfireIO/Hangfire。这些任务仍然存在于apppool回收之外。

答案 2 :(得分:2)

我喜欢@Todd的解决方案。仅仅为了完整起见,但还有另一个选项尚未提及:

HostingEnvironment.QueueBackgroundWorkItem(cancellationToken =>
{
    // Some long-running job
});

注意:

“当ASP.NET必须回收时,它将通知后台工作(通过设置CancellationToken),然后等待最多30秒才能完成工作。如果后台工作未在该时间范围内完成,这项工作将神秘地消失。“

并且避免在此处使用带有注入的DbContext的服务方法,因为这不起作用。

来源: MariusSchulzStephenCleary

答案 3 :(得分:0)

如果您使用Asp.net Core,则可以使用IHostService