【问题标题】:Queue-Based Background Processing in ASP.NET MVC Web Application [closed]ASP.NET MVC Web 应用程序中基于队列的后台处理
【发布时间】:2010-11-22 00:06:17
【问题描述】:

如何在我的 ASP.NET MVC Web 应用程序中实现后台处理队列?虽然大多数数据更改、更新等需要立即可见,但还有其他不需要实时处理的更新,我想将其移交给优先级较低的后台进程,该进程将按照自己的节奏进行处理.

以 StackOverflow 的徽章奖励系统为例。通常您可能会采取特定的行动来授予您徽章,但实际的“奖励”发生在稍后(通常在 10 分钟到几个小时之后)。我认为这是通过单独的后台进程完成的,因为 SO 的工作在获得徽章后立即授予徽章并不重要。

所以,我正在尝试创建某种队列系统,我可以在其中填充任务(比如任何实现 ITask 接口的具有 Process() 方法的东西),最终将由单独的进程执行。

我将如何实施这样的系统?想法/提示/示例代码?

谢谢!

【问题讨论】:

    标签: c# asp.net-mvc


    【解决方案1】:

    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
    

    【讨论】:

    • 您有一个示例,说明如何最初将服务应用程序与 MSMQ“连接”,然后再连接到 ASP.NET MVC?这对我来说很新鲜。谢谢!
    • 您只需写入相应的队列即可。您的服务将调用 .Receive,而您想要从中向队列发送消息的页面将简单地调用“.Send”。我将用一个小例子进行更新。
    • 已更新。注意我没有显示创建队列的代码,如果它不存在的话。但这可以通过在 System.Messaging API 中使用类似的方法轻松找到。具体来说:MessageQueue.Create(...)。请注意,您还需要获得适当的权限。 (.SetPermissions)。
    • 调用 queue.Send(m) 完全异步正确吗?我将如何与 MVC 应用程序进行通信/如何获得有关队列中正在等待处理的通知?再次感谢!
    • queue.Send 会立即返回,是的。您通过另一个队列进行通信。您可以简单地等待消息,或者正如我之前暗示的那样,使用 CorrelationId 来确保您在调用 .Receive() 之前获得对您发送的消息的响应(queue.MessageReadPropertyFilter.CorrelationId。您可以使用 TimeSpan 调用 .Receive()超时,所以你可以这样做,并注意你还没有得到任何东西,所以在队列方面还没有完成处理。
    【解决方案2】:

    Jeff 在https://blog.stackoverflow.com/2008/07/easy-background-tasks-in-aspnet/ 发表了一篇很棒的帖子,展示了他最初是如何为 Stack Overflow 实现这一目标的

    虽然如果您可以选择它,它可能不如服务可靠,但它在过去为我提供了很好的非必要任务,并且我已经让它在虚拟主机环境中工作。

    【讨论】:

      【解决方案3】:

      刚刚在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);
      }
      

      注意:我个人不会使用网络服务器来运行后台任务。也不要重新发明轮子,我强烈建议使用Hangfire

      阅读 Hanselman HowToRunBackgroundTasksInASPNET 的这篇精彩文章

      【讨论】:

        猜你喜欢
        • 2015-10-07
        • 1970-01-01
        • 2023-04-09
        • 1970-01-01
        • 2010-09-21
        • 1970-01-01
        • 2014-10-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多