【问题标题】:Long-running MSMQ message processing. Limiting worker threads count长时间运行的 MSMQ 消息处理。限制工作线程数
【发布时间】:2016-03-23 12:23:26
【问题描述】:

环境

  • 宿主应用程序是 Windows 服务 (.NET 3.5);
  • 目前还不能切换到 .NET 4+ 框架。

过程

  • 处理一封邮件最多可能需要 5 分钟。
  • 使用异步模式接收消息(ReceiveCompleted 事件订阅):

    private void OnMessageReceived(object source, ReceiveCompletedEventArgs eventArgs) {
    
        var queue = (MessageQueue)source;
        Message m = null;
    
        try {                
            var processor = new Thread(() => {
                try {
                    // 1. process the message
                    // 2. send a feedback to m's response queue
                }
                catch(Exception ex) {
                    Logger.Log.Error(ex);
                    // 1. send a feedback to m's response queue
                } 
            };
            processor.Start();
        }
        catch(Exception ex) {
            Logger.Log.Error(ex);
        }
    
        queue.BeginReceive();
    }
    

问题

我猜在产生单独的工作线程之后应该有一些限制。

假设我想使用 1-5 个工作线程最多)处理消息,如果所有可用工作线程都忙,那么:

  • 当前消息的处理被省略,反馈被发送到响应队列(消息丢失);
  • 消息被发送回队列,反馈被发送(处理被推迟);

如果所有可用的工作人员都忙这部分是否意味着我必须实现类似于线程池的东西?

我已将 添加到问题中。这是由于我看到使用 Rx Buffering 的一些代码。我不太明白这是否适用于我的情况。我可以在我的情况下使用 Rx 吗?

【问题讨论】:

    标签: system.reactive .net multithreading system.reactive msmq messaging


    【解决方案1】:

    如果您的服务由 IIS 托管,IIS 可能会阻止这种情况,但您可以尝试使用ThreadPool,尤其是使用它的SetMaxThreads 方法。请注意,您不能将它们设置为低于当前的处理器数量,但限制是应用程序范围内的(备注指出这可能对您的应用程序正在使用的库产生不利影响),并且取决于托管服务的主机可能防止您以这种方式设置线程。

    您可以尝试运行自己的代码,实现private static Queue<Thread> threadPool;,使用所需的线程数对其进行静态初始化,然后执行以下操作:

    var processor = threadPool.Dequeue();
    ...
    // there's no easy thread-safe way to check this in .net 3.5 - 
    // if you can use concurrent queue you could do this after checking if 
    // there's anything available in the queue with a ConcurrentQueue<Thread>
    //queue.BeginReceive(); // call this from the end of your thread execution now
    

    您的线程可以在完成处理后将Enqueue 自己返回到threadPool 队列,并在MSMQ queue 对象上调用BeginReceive() 以便进程可以继续(将queue 传递给此处记录的线程https://msdn.microsoft.com/en-us/library/ts553s52(v=vs.85).aspx)。

    如果您对如何在 .NET 3.5 中实现 ConcurrentQueue 感兴趣,您可以随时查看 Reference Source - 但就我个人而言,我宁愿硬着头皮升级到最新的 . NET 版本。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-03-07
      • 2016-04-12
      • 2011-09-09
      • 2023-03-17
      • 1970-01-01
      • 1970-01-01
      • 2010-11-05
      相关资源
      最近更新 更多