【问题标题】:Most efficient way to monitor a queue监控队列的最有效方法
【发布时间】:2009-06-23 15:09:23
【问题描述】:

监控队列最有效的方法是什么。

以下代码是最大的资源消耗:

/// <summary>
/// Starts the service.
/// </summary>
private void StartService()
{
    while (true)
    {
        //the check on count is not thread safe
        while (_MessageQueue.Count > 0)
        {
            Common.IMessage message;
            // the call to GetMessageFromQueue is thread safe
            if (_MessageQueue.GetMessageFromQueue(out message) == true)
            {
                if (message.RoutingInfo == Devices.Common.MessageRoutingInfo.ToDevice)
                {
                    _Port.SerialPort.WriteLine(message.Message);
                }
                if (message.RoutingInfo == Devices.Common.MessageRoutingInfo.FromDevice)
                {
                    OnDeviceMessageReceived(new Common.DeviceMessageArgs(message.Message));
                }
            }
        }
    }
}

Start Service 在后台线程上运行,对 _MessageQueue.Count 的调用不是线程安全的,我没有锁定 MessageQueue 中的计数。但是,我确实锁定了 _MessageQueue.GetMessageFromQueue 的实现。 我采取的方法有效吗?每次队列从 0 计数到大于零时,我是否应该引发一个事件?

【问题讨论】:

    标签: c# .net performance


    【解决方案1】:

    您可能应该在该方法中包含某种类型的线程睡眠,否则它将使用 100% 的 CPU。或者,您可以创建一个等待句柄,并在将消息添加到队列时设置它。

    【讨论】:

    • 除非你无法控制生产者,否则不要睡觉。使用事件或信号进行适当的等待/通知。
    • 为什么是垫子?我可以控制生产者。我应该在将项目添加到队列时引发事件吗?我会调查等待句柄。
    【解决方案2】:

    如果我没有遗漏任何内容 - 您正在 _messageQueue.Count 属性上忙着等待。 我会尝试做类似的事情: http://msdn.microsoft.com/en-us/library/yy12yx1f.aspx

    【讨论】:

      【解决方案3】:

      您可以使用 NetMsmqBinding 将 MSMQ 消息直接消费到 WCF 中,而不是主动轮询队列

      http://msdn.microsoft.com/en-us/library/ms789008.aspx

      希望这会有所帮助。

      【讨论】:

        【解决方案4】:

        _MessageQueue 是否仅在您的代码中使用?然后你可以将它包装在这样的类中:

        public class BlockingMessageQueue {
          private readonly MyMessageQueue queue;
          private readonly Semaphore signal;
        
          public BlockingMessageQueue(MyMessageQueue queue) {
            this.queue = queue;
            this.signal = new Semaphore(0, int.MaxValue);
          }
        
          public void Enqueue(IMessage message) {
            lock (this.queue) {
              this.queue.Send(message);
            }
            this.signal.Release();
          }
        
          public IMessage Dequeue() {
            this.signal.WaitOne();
            IMessage message;
            lock (this.queue) {
              var success = this.queue.GetMessageFromQueue(out message);
              Debug.Assert(success);
            }
            return message;
          }
        }
        

        Dequeue 将阻塞直到有消息可用,因此如果没有可用消息,则不会浪费周期。

        使用示例:

        var queue = new BlockingMessageQueue(_MessageQueue);
        
        while (true) {
          var message = queue.Dequeue();
        
          if (message.RoutingInfo == Devices.Common.MessageRoutingInfo.ToDevice)
          {
            _Port.SerialPort.WriteLine(message.Message);
          }
          else if (message.RoutingInfo == Devices.Common.MessageRoutingInfo.FromDevice)
          {
            OnDeviceMessageReceived(new Common.DeviceMessageArgs(message.Message));
          }
        }
        

        【讨论】:

        • 非常感谢,我一定会试一试的。我会让你知道它的表现。谢谢
        猜你喜欢
        • 2011-01-28
        • 2012-02-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-07-03
        • 2012-11-08
        • 2011-09-06
        相关资源
        最近更新 更多