一、MSMQ简介
MSMQ(微软消息队列)是Windows操作系统中消息应用程序的基础,是用于创建分布式、松散连接的消息通讯应用程序的开发工具。消息队列
和电子邮件有着很多相似处,他们都包含多个属性,用于保存消息,消息类型中都指出发送者和接收者的地址;然而他们的用处却有着很大的
区别:消息队列的发送者和接收者是应用程序,而电子邮件的发送者和接收者通常是人。如同电子邮件一样,消息队列的发送和接收也不需要
发送者和接收者同时在场,可以存储在消息队列或是邮件服务器中。
二、消息队列的安装
默认情况下安装操作系统是不安装消息队列的,你可以在控制面板中找到添加/删除程序,然后选择添加/删除Windows组件一项,然后选择应
用程序服务器,双击它进入详细资料中选择消息队列一项进行安装,如图:
![]()
![]()
![]()
三、消息队列类型
消息对列分为3类:
公共队列
MachineName\QueueName
能被别的机器所访问,如果你的多个项目中用到消息队列,那么你可以把队列定义为公共队列
专用队列
MachineName\Private$\QueueName
只针对于本机的程序才可以调用的队列,有些情况下为了安全起见定义为私有队列。
日志队列
MachineName\QueueName\Journal$
四、消息队列的创建
MessageQueue Mq=new MessageQueue(“.\\private$\\Mymq”);
通过Path属性引用消息队列的代码也十分简单:
MessageQueue Mq=new MessageQueue();
Mq.Path=”.\\private$\\Mymq”;
使用 Create 方法可以在计算机上创建队列:
System.Messaging.MessageQueue.Create(@".\private$\Mymq");
这里注意由于在C#中要记住用反斜杠将“\”转义。
由于消息对列所放置的地方经常改变,所以建议消息队列路径不要写死,建议放在配置文件中。
五、消息的发送
消息的发送可以分为简单消息和复杂消息,简单消息类型就是常用的数据类型,例如整型、字符串等数据;复杂消息的数据类型通常对应于系
统中的复杂数据类型,例如结构,对象等等。
Mq.Send("Hello!");
在这里建议你可以事先定义一个对象类,然后发送这个对象类的实例对象,这样以后无论在增加什么发送信息,只需在对象类中增加
相应的属性即可。
六、消息的接收和阅读
(1)同步接收消息
接收消息的代码很简单:
Mq.Receive();
Mq.Receive(TimeSpan timeout); //设定超时时间
Mq.ReceiveById(ID);
Mq.Peek();
通过Receive方法接收消息同时永久性地从队列中删除消息;
通过Peek方法从队列中取出消息而不从队列中移除该消息。
如果知道消息的标识符(ID),还可以通过ReceiveById方法和PeekById方法完成相应的操作。
(2)异步接受消息
利用委托机制:
MessQueue.ReceiveCompleted +=new ReceiveCompletedEventHandler(mq_ReceiveCompleted);
(3)消息阅读
在应用程序能够阅读的消息和消息队列中的消息格式不同,应用程序发送出去的消息经过序列化以后才发送给了消息队列
而在接受端必须反序列化,利用下面的代码可以实现:
public void mq_ReceiveCompleted(object sender, System.Messaging.ReceiveCompletedEventArgs e)
{
System.Messaging.Message m = MessQueue.EndReceive(e.AsyncResult);
m.Formatter = new System.Messaging.XmlMessageFormatter(new string[]{"System.String,mscorlib"});
Console.WriteLine("Message: " + (string)m.Body);
MessQueue.BeginReceive() ;
}
反序列化还有另一种写法:
m.Formatter = new XmlMessageFormatter ( new Type [] { typeof (string) } );
七、由于消息队列的代码有些是固定不便的,所以把这些代码封装成一个类方便以后使用:
1
using System;
2
using System.Messaging;
3
using System.Threading;
5![]()
6
namespace LoveStatusService
7![]()
![]()
{
8![]()
/**//// <summary>
9
/// Summary description for Msmq.
10
/// </summary>
11
public class Msmq
12![]()
{
13
public Msmq()
14![]()
{
15
//
16
// TODO: Add constructor logic here
17
//
18
}
19![]()
20
21
private MessageQueue _messageQueue=null;
22
//最大并发线程数
23
private static int MAX_WORKER_THREADS=Convert.ToInt32( System.Configuration.ConfigurationSettings.AppSettings["MAX_WORKER_THREADS"].ToString());
24
//Msmq路径
25
private static string MsmqPath=System.Configuration.ConfigurationSettings.AppSettings["LoveStatusMQPath"];
26
//等待句柄
27
private WaitHandle[] waitHandleArray = new WaitHandle[MAX_WORKER_THREADS];
28
//任务类型
29
//1. Send Email 2. Send Message 3. Send Email and Message
30
private string TaskType=System.Configuration.ConfigurationSettings.AppSettings["TaskType"];
31
public MessageQueue MessQueue
32![]()
{
33
get
34![]()
{
35
36
if (_messageQueue==null)
37![]()
{
38
if(MessageQueue.Exists(MsmqPath))
39![]()
{
40
_messageQueue = new MessageQueue(MsmqPath);
41
}
42
else
43![]()
{
44
_messageQueue = MessageQueue.Create(MsmqPath);
45
}
46
}
47
48![]()
49
return _messageQueue;
50
}
51
}
52
53![]()
54![]()
Private Method#region Private Method
55![]()
56
private void mq_ReceiveCompleted(object sender, System.Messaging.ReceiveCompletedEventArgs e)
57![]()
{
58
MessageQueue mqq = (MessageQueue)sender;
59
System.Messaging.Message m = mqq.EndReceive(e.AsyncResult);
60
//m.Formatter = new System.Messaging.XmlMessageFormatter(new string[]{"System.String,mscorlib"});
61![]()
m.Formatter =new System.Messaging.XmlMessageFormatter(new Type[]
{typeof(UserObject)}) ;
62
//log.Info("Receive UserID: " + (string)m.Body) ;
63
UserObject obj=(UserObject)m.Body ;
64
long curUserId=obj.curUserID ;
65
long oppUserId=obj.oppUserID;
66
string curUserName=obj.curUserName;
67
string oppUserName=obj.oppUserName;
68
string curEmail=obj.curEmail ;
69
string oppEmail=obj.oppEmail;
70
string subject =obj.subject ;
71
string body=obj.body ;
72
//AppLog.log.Info("curUserId:"+curUserId) ;
73
//AppLog.log.Info("oppUserId:"+oppUserId) ;
74
AppLog.log.Info("==type="+TaskType) ;
75
switch(TaskType)
76![]()
{
77
//Email
78
case "1":
79
EmailForMQ.SendEmailForLoveStatus(curEmail,oppEmail,curUserName,oppUserName,subject) ;
80
AppLog.log.Info("==Send to=="+oppEmail) ;
81
break;
82
//Message
83
case "2":
84
MessageForMQ.SendMessage(curUserId,oppUserId,subject,body) ;
85
AppLog.log.Info("==Send Msg to=="+oppUserId) ;
86
break;
87
//Email and Message
88
case "3":
89
EmailForMQ.SendEmailForLoveStatus(curEmail,oppEmail,curUserName,oppUserName,subject) ;
90
AppLog.log.Info("==Send to=="+oppEmail) ;
91
MessageForMQ.SendMessage(curUserId,oppUserId,subject,body) ;
92
AppLog.log.Info("==Send Msg to=="+oppUserId) ;
93
break;
94
default:
95
break;
96![]()
97
}
98
mqq.BeginReceive() ;
99![]()
100
}
101![]()
102
#endregion
103![]()
104![]()
Public Method#region Public Method
105![]()
106
//一个将对象发送到队列的方法,这里发送的是对象
107
public void SendUserIDToMQ(object arr)
108![]()
{
109
MessQueue.Send(arr) ;
110
Console.WriteLine("Ok") ;
111
Console.Read() ;
112
}
113![]()
114
//同步接受队列内容的方法
115
public void ReceiveFromMQ()
116![]()
{
117
Message ms=new Message() ;
118
119
//ms=MessQueue.Peek();
120
try
121![]()
{
122
ms=MessQueue.Receive(new TimeSpan(0,0,5));
123
if(ms!=null)
124![]()
{
125![]()
ms.Formatter = new XmlMessageFormatter ( new Type []
{ typeof (string) } );
126
AppLog.log.Info((string)ms.Body) ;
127
}
128
}
129
catch(Exception ex)
130![]()
{
131
132
}
133
134
135
}
136![]()
137
//开始监听工作线程
138
public void startListen()
139![]()
{
140
AppLog.log.Info("--Thread--"+MAX_WORKER_THREADS) ;
141
MessQueue.ReceiveCompleted +=new ReceiveCompletedEventHandler(mq_ReceiveCompleted);
142
143
//异步方式,并发
144
145
for(int i=0; i<MAX_WORKER_THREADS; i++)
146![]()
{
147
// Begin asynchronous operations.
148
waitHandleArray[i] = MessQueue.BeginReceive().AsyncWaitHandle;
149
}
150![]()
151
AppLog.log.Info("------Start Listen--------") ;
152![]()
153
return;
154![]()
155
}
156![]()
157
158
//停止监听工作线程
159
public void stopListen()
160![]()
{
161![]()
162
for(int i=0;i<waitHandleArray.Length;i++)
163![]()
{
164![]()
165
try
166![]()
{
167
waitHandleArray[i].Close();
168
}
169
catch
170![]()
{
171
AppLog.log.Info("---waitHandleArray[i].Close() Error!-----") ;
172
}
173![]()
174
}
175![]()
176
try
177![]()
{
178
// Specify to wait for all operations to return.
179
WaitHandle.WaitAll(waitHandleArray,1000,false);
180
}
181
catch
182![]()
{
183
AppLog.log.Info("---WaitHandle.WaitAll Error!-----") ;
184
}
185
AppLog.log.Info("------Stop Listen--------") ;
186![]()
187
}
188![]()
189
#endregion
190
191
192![]()
193
194
}
195
}
196![]()
UserObject的代码
1
using System;
2![]()
3
namespace Goody9807
4![]()
![]()
{
5![]()
/**//// <summary>
6
/// 用与在MQ上传输数据的对象
7
/// </summary>
8
public class UserObject
9![]()
{
10
public UserObject()
11![]()
{
12
//
13
// TODO: Add constructor logic here
14
//
15
}
16![]()
17
private long _curUserID;
18
public long curUserID
19![]()
{
20
get
21![]()
{
22
return _curUserID;
23
}
24
set
25![]()
{
26
_curUserID=value;
27
}
28
}
29![]()
30
private string _curUserName="";
31
public string curUserName
32![]()
{
33
get
34![]()
{
35
return _curUserName;
36
}
37
set
38![]()
{
39
_curUserName=value;
40
}
41
}
42![]()
43
private string _curEmail="";
44
public string curEmail
45![]()
{
46
get
47![]()
{
48
return _curEmail;
49
}
50
set
51![]()
{
52
_curEmail=value;
53
}
54
}
55![]()
56![]()
57
private long _oppUserID;
58
public long oppUserID
59![]()
{
60
get
61![]()
{
62
return _oppUserID;
63
}
64
set
65![]()
{
66
_oppUserID=value;
67
}
68
}
69![]()
70
private string _oppUserName="";
71
public string oppUserName
72![]()
{
73
get
74![]()
{
75
return _oppUserName;
76
}
77
set
78![]()
{
79
_oppUserName=value;
80
}
81
}
82![]()
83
private string _oppEmail="";
84
public string oppEmail
85![]()
{
86
get
87![]()
{
88
return _oppEmail;
89
}
90
set
91![]()
{
92
_oppEmail=value;
93
}
94
}
95![]()
96
private string _subject ="";
97
public string subject
98![]()
{
99
get
100![]()
{
101
return _subject;
102
}
103
set
104![]()
{
105
_subject=value;
106
}
107
}
108![]()
109
private string _body="";
110
public string body
111![]()
{
112
get
113![]()
{
114
return _body;
115
}
116
set
117![]()
{
118
_body=value;
119
}
120
}
121
}
122
}
123![]()
另一个同事写的封装类
![]()
![]()
1
using System;
2![]()
3
using System.Threading;
4![]()
5
using System.Messaging;
6![]()
7
8![]()
9
namespace Wapdm.SmsApp
10![]()
11![]()
![]()
{
12![]()
13![]()
/**//// <summary>
14![]()
15
/// <para>
16![]()
17
/// A Logger implementation that writes messages to a message queue.
18![]()
19
/// The default event formatter used is an instance of XMLEventFormatter
20![]()
21
/// </para>
22![]()
23
/// </summary>
24![]()
25
public sealed class MsgQueue
26![]()
27![]()
{
28![]()
29
30![]()
31
private const string BLANK_STRING = "";
32![]()
33
private const string PERIOD = @".\private$"; //".";
34![]()
35
private const string ELLIPSIS = "
";
36![]()
37
38![]()
39
private string serverAddress;
40![]()
41
private string queueName;
42![]()
43
private string queuePath;
44![]()
45
46![]()
47
private bool IsContextEnabled;
48![]()
49
50![]()
51
private MessageQueue queue;
52![]()
53
54![]()
55
private object queueMonitor = new object();
56![]()
57
58![]()
59![]()
private MsgQueue()
{}
60![]()
61
62![]()
63
public static MsgQueue mq = null;
64![]()
65
public static WaitHandle[] waitHandleArray = new WaitHandle[Util.MAX_WORKER_THREADS];
66![]()
67
68![]()
69
public MsgQueue(string _serverAddress, string _queueName, string _summaryPattern)
70![]()
71![]()
{
72![]()
73
if ((_serverAddress == null) || (_queueName == null) || (_summaryPattern == null))
74![]()
75![]()
{
76![]()
77
throw new ArgumentNullException();
78![]()
79
}
80![]()
81
ServerAddress = _serverAddress;
82![]()
83
QueueName = _queueName;
84![]()
85
IsContextEnabled = true;
86![]()
87
}
88![]()
89
90![]()
91
public MsgQueue(string _serverAddress, string _queueName)
92![]()
93![]()
{
94![]()
95
if ((_serverAddress == null) || (_queueName == null))
96![]()
97![]()
{
98![]()
99
throw new ArgumentNullException();
100![]()
101
}
102![]()
103
ServerAddress = _serverAddress;
104![]()
105
QueueName = _queueName;
106![]()
107
IsContextEnabled = true;
108![]()
109
}
110![]()
111
112![]()
113
public MsgQueue(string _queueName)
114![]()
115![]()
{
116![]()
117
if (_queueName == null)
118![]()
119![]()
{
120![]()
121
throw new ArgumentNullException();
122![]()
123
}
124![]()
125
serverAddress = PERIOD;
126![]()
127
QueueName = _queueName;
128![]()
129
IsContextEnabled = true;
130![]()
131
if ( IsContextEnabled == false )
132![]()
133
throw new ArgumentNullException();
134![]()
135
}
136![]()
137
138![]()
139
public string ServerAddress
140![]()
141![]()
{
142![]()
143
get
144![]()
145![]()
{
146![]()
147
return serverAddress;
148![]()
149
}
150![]()
151
set
152![]()
153![]()
{
154![]()
155
if (value == null)
156![]()
157![]()
{
158![]()
159
value = PERIOD;
160![]()
161
}
162![]()
163
value = value.Trim();
164![]()
165
if (value.Equals(BLANK_STRING))
166![]()
167![]()
{
168![]()
169
throw new ArgumentException("Invalid value (must contain non-whitespace characters)");
170![]()
171
}
172![]()
173
lock (queueMonitor)
174![]()
175![]()
{
176![]()
177
serverAddress = value;
178![]()
179
queuePath = serverAddress + '\\' + queueName;
180![]()
181
InitializeQueue();
182![]()
183
}
184![]()
185
}
186![]()
187
}
188![]()
189
190![]()
191
public string QueueName
192![]()
193![]()
{
194![]()
195
get
196![]()
197![]()
{
198![]()
199
return queueName;
200![]()
201
}
202![]()
203
set
204![]()
205![]()
{
206![]()
207
if (value == null)
208![]()
209![]()
{
210![]()
211
throw new ArgumentNullException();
212![]()
213
}
214![]()
215
value = value.Trim();
216![]()
217
if (value.Equals(BLANK_STRING))
218![]()
219![]()
{
220![]()
221
throw new ArgumentException("Invalid value (must contain non-whitespace characters)");
222![]()
223
}
224![]()
225
lock (queueMonitor)
226![]()
227![]()
{
228![]()
229
queueName = value;
230![]()
231
queuePath = serverAddress + '\\' + queueName;
232![]()
233
InitializeQueue();
234![]()
235
}
236![]()
237
}
238![]()
239
}
240![]()
241
242![]()
243
private void InitializeQueue()
244![]()
245![]()
{
246![]()
247
lock (queueMonitor)
248![]()
249![]()
{
250![]()
251
if (queue != null)
252![]()
253![]()
{
254![]()
255![]()
try
{ queue.Close(); }
256![]()
257![]()
catch
{}
258![]()
259
queue = null;
260![]()
261
}
262![]()
263
264![]()
265
try
266![]()
267![]()
{
268![]()
269
if(!MessageQueue.Exists(queuePath))
270![]()
271
MessageQueue.Create(queuePath);
272![]()
273
}
274![]()
275![]()
catch
{}
276![]()
277
try
278![]()
279![]()
{
280![]()
281
queue = new MessageQueue(queuePath);
282![]()
283
queue.SetPermissions("EveryOne",MessageQueueAccessRights.FullControl);
284![]()
285![]()
queue.Formatter = new XmlMessageFormatter(new Type[]
{typeof(MoMsg)});
286![]()
287
}
288![]()
289
catch (Exception e)
290![]()
291![]()
{
292![]()
293![]()
try
{ queue.Close(); }
294![]()
295![]()
catch
{}
296![]()
297
queue = null;
298![]()
299
throw new ApplicationException("Couldn't open queue at '" + queuePath + "': " + e.GetType().FullName + ": " + e.Message);
300![]()
301
}
302![]()
303
304![]()
305
}
306![]()
307
}
308![]()
309
310![]()
311
private void AcquireResources()
312![]()
313![]()
{
314![]()
315
InitializeQueue();
316![]()
317
}
318![]()
319
320![]()
321
public void ReleaseResources()
322![]()
323![]()
{
324![]()
325
lock (queueMonitor)
326![]()
327![]()
{
328![]()
329
if (queue != null)
330![]()
331![]()
{
332![]()
333
try
334![]()
335![]()
{
336![]()
337
queue.Close();
338![]()
339
}
340![]()
341![]()
catch
{}
342![]()
343
queue = null;
344![]()
345
}
346![]()
347
}
348![]()
349
}
350![]()
351
352![]()
353
//阻塞方式
354![]()
355
public MoMsg Read( )
356![]()
357![]()
{
358![]()
359
MoMsg _event = null;
360![]()
361
lock (queueMonitor)
362![]()
363![]()
{
364![]()
365
if (queue == null)
366![]()
367![]()
{
368![]()
369
InitializeQueue();
370![]()
371
}
372![]()
373
try
374![]()
375![]()
{
376![]()
377
Message message = queue.Receive( new TimeSpan(0,0,1) );//等待10秒
378![]()
379
_event = (MoMsg) (message.Body);
380![]()
381
return _event;
382![]()
383
}
384![]()
385
catch (Exception )
386![]()
387![]()
{
388![]()
389![]()
try
{ queue.Close(); }
390![]()
391![]()
catch
{}
392![]()
393
queue = null;
394![]()
395
}
396![]()
397
}
398![]()
399
return null;
400![]()
401
}
402![]()
403
404![]()
405
public void Write(MoMsg _event)
406![]()
407![]()
{
408![]()
409
if (_event == null)
410![]()
411![]()
{
412![]()
413
return;
414![]()
415
}
416![]()
417
lock (queueMonitor)
418![]()
419![]()
{
420![]()
421
try
422![]()
423![]()
{
424![]()
425
if (queue == null)
426![]()
427![]()
{
428![]()
429
InitializeQueue();
430![]()
431
}
432![]()
433
434![]()
435
Message message = new Message();
436![]()
437
message.Priority = _event.Priority;
438![]()
439
message.Recoverable = true;
440![]()
441
message.Body = _event; //eventFormatter.Format(_event);
442![]()
443
444![]()
445
queue.Send(message);
446![]()
447
}
448![]()
449
catch (Exception e)
450![]()
451![]()
{
452![]()
453![]()
try
{ queue.Close(); }
454![]()
455![]()
catch
{}
456![]()
457
queue = null;
458![]()
459
Util.Log.log("Couldn't write Message (" + e.GetType().FullName + ": " + e.Message + ")");
460![]()
461
}
462![]()
463
}
464![]()
465
}
466![]()
467
468![]()
469
public static bool statusTest()
470![]()
471![]()
{
472![]()
473
bool reValue = false;
474![]()
475
try
476![]()
477![]()
{
478![]()
479
MessageEnumerator re = mq.queue.GetMessageEnumerator();
480![]()
481
bool rev = re.MoveNext();
482![]()
483
reValue = true;
484![]()
485
}
486![]()
487
catch
488![]()
489![]()
{
490![]()
491
reValue = false;
492![]()
493
}
494![]()
495
496![]()
497
return reValue;
498![]()
499
}
500![]()
501
502![]()
503
public static void startListen()
504![]()
505![]()
{
506![]()
507
mq = new MsgQueue(Util.MqName);
508![]()
509
510![]()
511
mq.queue.ReceiveCompleted +=new ReceiveCompletedEventHandler(queue_ReceiveCompleted);
512![]()
513
514![]()
515
//异步方式,并发
516![]()
517
for(int i=0; i<Util.MAX_WORKER_THREADS; i++)
518![]()
519![]()
{
520![]()
521
// Begin asynchronous operations.
522![]()
523
waitHandleArray[i] =
524![]()
525
mq.queue.BeginReceive().AsyncWaitHandle;
526![]()
527
}
528![]()
529
530![]()
531
return;
532![]()
533
}
534![]()
535
536![]()
537
public static void stopListen()
538![]()
539![]()
{
540![]()
541
542![]()
543
for(int i=0;i<waitHandleArray.Length;i++)
544![]()
545![]()
{
546![]()
547
try
548![]()
549![]()
{
550![]()
551
waitHandleArray[i].Close();
552![]()
553
}
554![]()
555
catch
556![]()
557![]()
{
558![]()
559
//忽略错误
560![]()
561
}
562![]()
563
}
564![]()
565
566![]()
567
try
568![]()
569![]()
{
570![]()
571
// Specify to wait for all operations to return.
572![]()
573
WaitHandle.WaitAll(waitHandleArray,1000,false);
574![]()
575
}
576![]()
577
catch
578![]()
579![]()
{
580![]()
581
//忽略错误
582![]()
583
}
584![]()
585
}
586![]()
587
588![]()
589
private static void queue_ReceiveCompleted(object sender, ReceiveCompletedEventArgs e)
590![]()
591![]()
{
592![]()
593
// Connect to the queue.
594![]()
595
MessageQueue mqq = (MessageQueue)sender;
596![]()
597
598![]()
599
// End the asynchronous Receive operation.
600![]()
601
Message m = mqq.EndReceive(e.AsyncResult);
602![]()
603
604![]()
605
Util.ProcessMo((MoMsg)(m.Body));
606![]()
607
608![]()
609
if(Util.isRunning)
610![]()
611![]()
{
612![]()
613
// Restart the asynchronous Receive operation.
614![]()
615
mqq.BeginReceive();
616![]()
617
}
618![]()
619
620![]()
621
return;
622![]()
623
}
624![]()
625
}
626![]()
627
}
628![]()
629![]()