最近小小地研究了一下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 } }