如何在ASP.NET MVC Web应用程序中实现后台处理队列?虽然大多数数据更改,更新等需要立即可见,但还有其他更新不需要实时处理,我希望将其移交给优先级较低的后台进程,后者将按照自己的进度处理它
例如,采用StackOverflow的徽章奖励系统。通常,您可以采取特定的行动来奖励您的徽章,但实际的“奖励”会在以后发生(通常在10分钟到几个小时之后)。我认为这是通过一个单独的后台流程来完成的,因为SO的工作在获得时立即颁发徽章并不重要。
所以,我正在尝试创建某种类型的队列系统,我可以在其中填充任务(比如任何实现ITask接口的东西,它将有一个Process()方法),最终将由一个单独的进程执行。
我如何实施这样的系统?想法/提示/示例代码?
谢谢!
答案 0 :(得分:20)
Windows服务和MSMQ与他们通信(如果您需要)。
- 编辑
略微扩大。
你将创建几个服务,具体取决于你想做什么,让它们都运行各种睡眠级别的无尽线程,做你想做的事。然后,他们将适当地更新数据库,您不必在客户端做任何事情。
您可能希望从管理员的角度与他们进行交互,因此您可能有一个他们听取管理员命令的MSMQ。根据您的实现,您可能需要因某些原因重新启动它们,或者可能只是“强制”运行他们想要做的任何事情。
因此,您将使用MSMQ专用队列来执行此操作(System.Messaging命名空间)。关于MSMQ的主要注意事项之一是消息需要< 4meg。因此,如果您打算发送大对象图,请先将其序列化到文件中,然后只发送文件名。
MSMQ非常漂亮。如果需要,您可以根据“关联ID”发送,但由于某些有趣的原因,相关ID必须采用以下形式:
{guid}\1
其他任何东西都不起作用(至少在框架的2.0版本中,代码可能已经改变了。)
- 编辑
示例,根据要求:
using System.Messaging;
...
MessageQueue queue = new MessageQueue(".\\Private$\\yourqueue");
queue.Formatter = new BinaryMessageFormatter();
Message m = new Message();
m.Body = "your serialisable object or just plain string";
queue.Send(m);
// on the other side
MessageQueue queue = new MessageQueue(".\\Private$\\yourqueue");
queue.Formatter = new BinaryMessageFormatter();
Message m = queue.Receive();
string s = m.Body as string;
// s contains that string now
答案 1 :(得分:11)
Jeff有一篇很棒的文章,展示了他最初是如何在http://blog.stackoverflow.com/2008/07/easy-background-tasks-in-aspnet/
上实现Stack Overflow的虽然它可能不如服务那么可靠,如果这对你来说是一个选项,它在过去对我非常重要的任务很有帮助,而且我已经在虚拟主机环境中工作了。
答案 2 :(得分:5)
在ASP.NET MVC中搜索后台进程时发现了这个问题。 (在.NET 4.5.2之后可用)
public ActionResult InitiateLongRunningProcess(Emails emails)
{
if (ModelState.IsValid)
{
HostingEnvironment.QueueBackgroundWorkItem(ct => LongRunningProcessAsync(emails.Email));
return RedirectToAction("Index", "Home");
}
return View(user);
}
注意:我个人不会使用Web服务器来运行后台任务。也不要重新发明轮子,我强烈建议使用Hangfire。
阅读Hanselman撰写的这篇精彩文章HowToRunBackgroundTasksInASPNET