最近小小地研究了一下MSMQ,如果把MSMQ用的灵活自如,炉火纯青那要花大功夫了,而且不能简单的用.net提供的MessageQueue类了,这个类提供的功能太少。下面的包装类只提供了插入新数据到MSMQ和从MSMQ取数据,还有一个小特色,可以限制Queue里数据数目,如果达到指定数量,就sleep一段时间。
首先,加入引用System.Messaging.dll, 以及Interop所使用的com:Microsoft Message Queue 3.0 Object Libray.

代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Messaging;
using System.Runtime.InteropServices;

namespace Common
{
    public class MSMQ<T> : IDisposable
    {
        MessageQueue queue = null;

        int upperLimit = 0;

        public MSMQ(string qName)
            : this(qName, 0)
        {
        }

        public MSMQ(string qName, int limit)
        {
            if (!string.IsNullOrEmpty(qName) && !MessageQueue.Exists(qName))
            {
                MessageQueue.Create(qName, true);
            }
            queue = new MessageQueue(qName);

            upperLimit = limit;
        }


        public T Pop()
        {
            T element = default(T);
            try
            {
                // 30秒内获取Message,超过30秒会引发超时异常
                using (Message m = queue.Receive(new TimeSpan(0, 0, 30)))
                {
                    m.Formatter = new XmlMessageFormatter(new Type[] { typeof(T) });

                    element = (T)m.Body;
                }
            }
            catch (MessageQueueException exp)
            {
                if (CurrentCount != 0)
                    Console.WriteLine(exp.Message);
            }
            return element;
        }



        internal void Push(T[] elements)
        {
            if (elements != null)
            {
                foreach (T element in elements)
                {
                    Push(element);
                }
            }
        }

        public void Push(T element)
        {
            using (MessageQueueTransaction ms = new MessageQueueTransaction())
            {
                ms.Begin();

                using (System.Messaging.Message message = new System.Messaging.Message())
                {
                    message.Body = element;

                    message.Formatter = new System.Messaging.XmlMessageFormatter(new Type[] { typeof(T) });

                    // Put message into queue

                    queue.Send(message, ms);
                }
                ms.Commit();
            }

            //若达到设定的上限,sleep一分钟.
            while (upperLimit != 0 && (CurrentCount >= upperLimit))
            {
                System.Threading.Thread.Sleep(60000);
            }
        }

        private int CurrentCount
        {
            get
            {
                MSMQ.MSMQManagement msmq = new MSMQ.MSMQManagement();

                object server = null;
                object path = queue.Path;
                object format = null;

                msmq.Init(ref server, ref path, ref format);

                int count = msmq.MessageCount;

                Marshal.ReleaseComObject(msmq);

                return count;
            }
        }


        #region IDisposable Members

        public void Dispose()
        {
            if (queue != null)
                queue.Dispose();
            if (logger != null)
                logger.Dispose();
        }

        #endregion
    }
}