长时间运行的MSMQ消息处理。限制工作线程计数

时间:2016-03-23 12:23:27

标签: .net multithreading system.reactive msmq messaging

环境

  • 主机应用程序是 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 吗?

1 个答案:

答案 0 :(得分: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 BeginReceive()对象上调用queue以便进程可以继续(将queue传递给此处记录的帖子https://msdn.microsoft.com/en-us/library/ts553s52(v=vs.85).aspx)。

如果您对如何在.NET 3.5中实现ConcurrentQueue感兴趣,可以随时查看Reference Source - 但我个人认为关于升级到最新.NET版本的内容。