.Net下的MSMQ(微软消息队列)的同步异步调用
一、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) } );
七、由于消息队列的代码有些是固定不便的,所以把这些代码封装成一个类方便以后使用:
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
#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
#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的代码
using System;2

3
namespace Goody98074
{5
/// <summary>6
/// 用与在MQ上传输数据的对象7
/// </summary>8
public class UserObject9
{10
public UserObject()11
{12
//13
// TODO: Add constructor logic here14
//15
}16

17
private long _curUserID;18
public long curUserID19
{20
get21
{22
return _curUserID;23
}24
set25
{26
_curUserID=value;27
}28
}29

30
private string _curUserName="";31
public string curUserName32
{33
get34
{35
return _curUserName;36
}37
set38
{39
_curUserName=value;40
}41
}42

43
private string _curEmail="";44
public string curEmail45
{46
get47
{48
return _curEmail;49
}50
set51
{52
_curEmail=value;53
}54
}55

56

57
private long _oppUserID;58
public long oppUserID59
{60
get61
{62
return _oppUserID;63
}64
set65
{66
_oppUserID=value;67
}68
}69

70
private string _oppUserName="";71
public string oppUserName72
{73
get74
{75
return _oppUserName;76
}77
set78
{79
_oppUserName=value;80
}81
}82

83
private string _oppEmail="";84
public string oppEmail85
{86
get87
{88
return _oppEmail;89
}90
set91
{92
_oppEmail=value;93
}94
}95

96
private string _subject ="";97
public string subject98
{99
get100
{101
return _subject;102
}103
set104
{105
_subject=value;106
}107
}108

109
private string _body="";110
public string body111
{112
get113
{114
return _body;115
}116
set117
{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.SmsApp10

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 XMLEventFormatter20

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
try476

477
{478

479
MessageEnumerator re = mq.queue.GetMessageEnumerator();480

481
bool rev = re.MoveNext();482

483
reValue = true;484

485
}486

487
catch488

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
try548

549
{550

551
waitHandleArray[i].Close();552

553
}554

555
catch556

557
{558

559
//忽略错误560

561
}562

563
}564

565
566

567
try568

569
{570

571
// Specify to wait for all operations to return.572

573
WaitHandle.WaitAll(waitHandleArray,1000,false);574

575
}576

577
catch578

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
来源:http://www.cnblogs.com/goody9807/archive/2007/05/18/546572.html.Net下的MSMQ(微软消息队列)的同步异步调用的更多相关文章
- 【转】MSMQ 微软消息队列 简单 示例
MSMQ它的实现原理是:消息的发送者把自己想要发送的信息放入一个容器中(我们称之为Message),然后把它保存至一个系统公用空间的消息队列(Message Queue)中:本地或者是异地的消息接收程 ...
- 微软消息队列-MicroSoft Message Queue(MSMQ)队列的C#使用
目录 定义的接口 接口实现 建立队列工厂 写入队列 获取消息 什么是MSMQ Message Queuing(MSMQ) 是微软开发的消息中间件,可应用于程序内部或程序之间的异步通信.主要的机制是:消 ...
- 深入剖析 RabbitMQ —— Spring 框架下实现 AMQP 高级消息队列协议
前言 消息队列在现今数据量超大,并发量超高的系统中是十分常用的.本文将会对现时最常用到的几款消息队列框架 ActiveMQ.RabbitMQ.Kafka 进行分析对比.详细介绍 RabbitMQ 在 ...
- .net微软消息队列(msmq)简单案例
1.首先我们需要安装消息队列服务,它是独立的消息记录的服务,并保存在硬盘文件中. 我们添加名为:DMImgUpload的私有消息队列. 2.定义消息队列的连接字符串建议采用IP: (1)FormatN ...
- 【c#】队列(Queue)和MSMQ(消息队列)的基础使用
首先我们知道队列是先进先出的机制,所以在处理并发是个不错的选择.然后就写两个队列的简单应用. Queue 命名空间 命名空间:System.Collections,不在这里做过多的理论解释,这个东西非 ...
- 微软消息队列MessageQueue(MQ)
首先本地安装微软的消息队列服务器. 基础类: namespace Core.MessageQueueTest { public class TestQueue : IDisposable { prot ...
- 微软 消息队列 MessageQueue 简单使用
1.在服务电脑上打开 消息队列 ①进入控制面板>程序>启用或关闭windows功能 ②将需要的勾选(我自己全选了哈哈哈) ③我的电脑 右键 打开管理 见到消息队列 在专用队列上新建专用队列 ...
- PHP下用Memcache 实现消息队列
Memcache 一般用于缓存服务.但是很多时候,比如一个消息广播系统,需要一个消息队列.直接从数据库取消息,负载往往不行.如果将整个消息队列用一个key缓存到memcache里面, 对于一个很大的消 ...
- Linux下进程间通信方式——使用消息队列
一.什么是消息队列 消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法. 每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构.我们可以通过发送消息来避免命名管道的 ...
随机推荐
- ☀【CSS3】形状
CSS3shapeshttp://www.css3shapes.com/ <!DOCTYPE html> <html lang="zh-CN"> <h ...
- 老的acm & oj学习站点
1.网易小鱼博客 http://gisyhy.blog.163.com/blog/#m=0&t=1&c=fks_087069086082087064085081082095085084 ...
- [C# 网络编程系列]专题四:自定义Web浏览器
转自:http://www.cnblogs.com/zhili/archive/2012/08/24/WebBrowser.html 前言: 前一个专题介绍了自定义的Web服务器,然而向Web服务器发 ...
- slua 中使用 lua5.3
因为我们服务器极有可能要迁移到 skynet 上,它基于 lua5.3,而服务器和客户端会公用很多lua代码,所以在考虑在客户端 slua 中使用 lua5.3. 经过编译后,发现 slua 对 lu ...
- Poj 3683-Priest John's Busiest Day 2-sat,拓扑排序
Priest John's Busiest Day Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 8872 Accept ...
- 一步一步写一个简单通用的makefile(二)
这一篇源代码沿用上一篇的源代码hellomake.c hellofunc.c hellofunc.h makefile 但是代码内容和结构有变化,如下: . ├── include │ └── h ...
- Get the largest sum of contiguous subarray in an int array
When I finished reading this problem,I thought I could solve it by scanning every single subarray in ...
- How do I use a host name to look up an IP address?
The InetAddress class can be used to perform Domain Name Server (DNS) lookups. For example, you can ...
- Eclipse用法和技巧十二:快速复制一行
写代码的总有那么个时候需要Ctrl+c,Ctrl+v,在eclipse中如果遇到需要快速在一行代码的上下复制一行的话,有很方便的快捷键可以使用.将光标放到某一行,按住Ctrl+Alt+Down,即可以 ...
- C# 的异步
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.N ...