C# 如何在 ASP.NET Web API 中排队后台任务
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14710822/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to queue background tasks in ASP.NET Web API
提问by appsecguy
I have a webapi that is designed to process reports in a queue fashion. The steps the application takes are as follows:
我有一个 webapi,旨在以队列方式处理报告。应用程序的步骤如下:
- Receive content
- Map the content to an object and place it into the queue
- Poll for pending items in the queue
- Process items in queue one at a time
- 接收内容
- 将内容映射到一个对象并将其放入队列
- 轮询队列中的待处理项目
- 一次处理一个队列中的项目
I was thinking to use Entity Framework to create a database of queued items, such as:
我正在考虑使用实体框架来创建排队项目的数据库,例如:
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; }
}
My question - Is there a more efficient way, using NServiceBus, BlockingCollection or ConcurrentQeueue, than to constantly poll the database and pull out pending items one by one? I have not used queues before.
我的问题 - 有没有比使用 NServiceBus、BlockingCollection 或 ConcurrentQeueue 更有效的方法,而不是不断轮询数据库并一个一个地拉出待处理的项目?我以前没有使用过队列。
One thought is to create a queue of tasks, and on a separate thread process all pending tasks. Somewhat similar to Most efficient way to process a queue with threadsbut I want to ensure that I am going the most efficient route.
一个想法是创建一个任务队列,并在一个单独的线程上处理所有挂起的任务。有点类似于用线程处理队列的最有效方法,但我想确保我走的是最有效的路线。
EDIT: A big question I have here is the best way to display the progress to the user. Once the user submits content, he gets taken to a new page and can view the status by the batch identifier. Is MSMQ necessary, or NServiceBus, in order to notify the user? This seems like a variation of the REquest/Acknowledge/Push paradigm?
编辑:我在这里遇到的一个大问题是向用户显示进度的最佳方式。一旦用户提交内容,他就会被带到一个新页面并可以通过批次标识符查看状态。是否需要 MSMQ 或 NServiceBus 来通知用户?这似乎是请求/确认/推送范式的变体?
采纳答案by tugberk
IMHO, your ASP.NET Web API application shouldn't run those background tasks by itself. It should only be responsible to receive the request, stick it inside the queue (as you indicated) and return the response indicating the success or failure of the received message. You can use variety of messaging systems such as RabbitMQfor this approach.
恕我直言,您的 ASP.NET Web API 应用程序不应自行运行这些后台任务。它应该只负责接收请求,将其粘贴在队列中(如您所示)并返回指示接收消息成功或失败的响应。对于这种方法,您可以使用各种消息传递系统,例如RabbitMQ。
As for the notification, you have a few options. You can have an endpoint which the client can check whether the processing is completed or not. Alternatively, you could provide a streaming API endpoint which your client can subscribe to. This way, the client doesn't have to poll the server; the server can notify the clients which are connected. ASP.NET Web API has a great way of doing this. The following blog post explains how:
至于通知,您有几个选择。您可以有一个端点,客户端可以检查处理是否完成。或者,您可以提供客户端可以订阅的流 API 端点。这样,客户端不必轮询服务器;服务器可以通知连接的客户端。ASP.NET Web API 有一个很好的方法来做到这一点。以下博客文章解释了如何:
You can also consider SignalRfor this type of server to client notifications.
您还可以考虑将SignalR用于此类服务器到客户端通知。
The reason why background tasks are hard for ASP.NET Web API application is that you're responsible to keep the AppDomain alive. This is a hassle especially when you are hosting under IIS. The following blog posts explains really good what I mean:
ASP.NET Web API 应用程序的后台任务之所以困难,是因为您有责任让 AppDomain 保持活动状态。这很麻烦,尤其是当您在 IIS 下托管时。以下博客文章很好地解释了我的意思:
回答by Todd
It's a NuGet package and it's called HangFire - https://github.com/HangfireIO/Hangfire. The tasks persist even beyond apppool recycling.
它是一个 NuGet 包,名为 HangFire - https://github.com/HangfireIO/Hangfire。这些任务甚至在 apppool 回收之后仍然存在。
回答by Anytoe
I like @Todd's solution. Just for the sake of completeness, but there's another option not mentioned yet:
我喜欢@Todd 的解决方案。只是为了完整起见,但还有另一个选项尚未提及:
HostingEnvironment.QueueBackgroundWorkItem(cancellationToken =>
{
// Some long-running job
});
Note:
笔记:
"When ASP.NET has to recycle, it will notify the background work (by setting a CancellationToken) and will then wait up to 30 seconds for the work to complete. If the background work doesn't complete in that time frame, the work will mysteriously disappear."
“当 ASP.NET 必须回收时,它会通知后台工作(通过设置 CancellationToken),然后最多等待 30 秒让工作完成。如果后台工作没有在那个时间范围内完成,则工作会神秘消失。”
And avoid using service methods with an injected DbContext here as this won't work.
并避免在此处使用带有注入 DbContext 的服务方法,因为这将不起作用。
Sources: MariusSchulzand StephenCleary
回答by menxin
If you use Asp.net Core,you can use IHostService.
如果您使用 Asp.net Core,则可以使用IHostService。