PetShop 4.0学习笔记:消息队列MSMQ

直到今天才知道,在我们每天都在用的Window系统里还有这么好用的一个编程组件:消息队列.它能够解决在大数据量交换的情况下的性能问题,特别是BS系统的数据库性能.而且它的异步处理方式能给程序员最大的便利与最好的用户体验.

1.首先在需要进行消息队列的服务器上安装MSMQ,我的系统是win2003+iis6,所以这个安装选项在添加删除程序->windows组件->应用程序服务器内.默认是不安装的,需要手动选择.

2.建立消息队列的存放路径.这可以在windows的计算机管理内添加,也可以在程序中添加.我是在程序中添加.

3.在.net中要引用System.Messaging;

C#代码

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Messaging;
  4. namespace MSMQ
  5. {
  6. class Program
  7. {
  8. private const string path = @".\private$\ljz";
  9. private static MessageQueue queue = MessageQueue.Exists(path) ? new MessageQueue(path) : MessageQueue.Create(path, true);
  10. //private static List<string> list = new List<string>();
  11. public enum Level
  12. {
  13. Low,
  14. Normal,
  15. High
  16. }
  17. static void Main(string[] args)
  18. {
  19. Send("第一次!", Level.Low);
  20. Send("第二次!", Level.Normal);
  21. Send("第三次!", Level.High);
  22. Console.WriteLine(Receive());
  23. Console.WriteLine(Receive());
  24. Console.WriteLine(Receive());
  25. Send("异步第一次!", Level.Normal);
  26. Send("异步第二次!", Level.High);
  27. Send("异步第三次!", Level.Low);
  28. ReceiveByAsyn();
  29. //foreach (string str in list)
  30. //{
  31. //    Console.WriteLine(str);
  32. //}
  33. Console.ReadKey();
  34. }
  35. public static void Send(string content, Level level)
  36. {
  37. System.Messaging.Message message = new System.Messaging.Message();
  38. message.Formatter = new System.Messaging.BinaryMessageFormatter();
  39. message.Body = content;
  40. switch (level)
  41. {
  42. case Level.Low:
  43. message.Priority = MessagePriority.Low;
  44. break;
  45. case Level.High:
  46. message.Priority = MessagePriority.High;
  47. break;
  48. default:
  49. message.Priority = MessagePriority.Normal;
  50. break;
  51. }
  52. //MessageQueueTransaction tran = new MessageQueueTransaction();
  53. //try
  54. //{
  55. //    tran.Begin();
  56. //    queue.Send(message);
  57. //    tran.Commit();
  58. //}
  59. //catch
  60. //{
  61. //    tran.Abort();
  62. //}
  63. queue.Send(message, MessageQueueTransactionType.Automatic);
  64. }
  65. public static string Receive()
  66. {
  67. System.Messaging.Message message = queue.Receive();
  68. message.Formatter = new System.Messaging.BinaryMessageFormatter();
  69. return message.Body.ToString();
  70. }
  71. public static void ReceiveByAsyn()
  72. {
  73. queue.ReceiveCompleted += new ReceiveCompletedEventHandler(queue_ReceiveCompleted);
  74. queue.BeginReceive();
  75. }
  76. private static void queue_ReceiveCompleted(object sender, ReceiveCompletedEventArgs e)
  77. {
  78. MessageQueue queueTmp = sender as MessageQueue;
  79. System.Messaging.Message mess = queueTmp.EndReceive(e.AsyncResult);
  80. mess.Formatter = new System.Messaging.BinaryMessageFormatter();
  81. Console.WriteLine(mess.Body.ToString());
  82. //list.Add(mess.Body.ToString());
  83. queueTmp.BeginReceive();
  84. }
  85. }
  86. }

下面对以上代码作几点解释:

1.上面的代码没有加异常处理,其实像这类代码是一定要加异常处理的!

2.路径.消息队列有好几种,有的可以被别人访问,如公共队列,有的则只能自己访问,如:专用队列.具体的分类,请参看下面列出的参考文章.但不是每种都可以使用.象我这种工作组模式的电脑,只能使用专用队列,即只能自己访问自己.它们的路径写法是有区别的:

C#代码

  1. Public:  [MachineName]\[QueueName]
  2. Private:  [MachineName]\Private$\[QueueName]

3.使用消息队列有两个重要的类:System.Messaging.Message与System.Messaging.MessageQueue.我之所以列出全名,是因为在.net中有同名类,不要弄混了.下面的MessageQueue与Message特指上面两个类.

MessageQueue是消息队列对象,里面有两个重要的方法:Send与Receive.顾名思义,Send是向消息队列发送消息,Receive是从消息队列接收消息.

Message是消息对象.它有两个重要的属性Formatter是其内容序列化格式属性,Body是其存放内容的主体.在上面的例子中我放的是字符串,其实它还可以放对象,前提是对象必须可以被序列化.

根据以上说的内容,己经可以写出一个消息队列的Demo了,但是还不够实用,下面要说的是其一些实用的属性.

1.优先级.不可否认,在实际应用中消息是有优先级的,有的消息重要需要优先被处理有的消息则一般.如何体现呢?Message对象有Priority属性,它有8个等级,我在上面的例子中只用了其中三个.通过设置优先级,可以实现让重要的消息优先被处理.

2.事务.有时候,在传输数据的过程中,需要保证数据的一致性,在数据库中常常用到事务,其实这里也有事务,在上面的例子中56-66行代码是事务处理,但是写的比较累赘,其实可以采用67行的写法,让系统自己去维护.

3.异步处理.MessageQueue对象的Receive方法有个缺点,当队列中没有数据时线程会锁死,直到有新的数据进入.这其实是不好的.一种更好的处理方式是新开辟一个线程去处理,这样就不会影响现有的线程了.在.net中写法为例子的80与81行,让消息对象加载一个委托,然后把处理代码放在委托内.

代码的第11行,32-35行,90行是我有意注掉的,其实我想的是当异步处理消息时,所做的应该只是把数据取出来就可以了,不应该还在里面进行处理.而是在别的地方再对数据进行处理.我声明了个局部变量list,按理说第90行数据取出来后应该能加入这个list,然而事实是取出的数据有时能加进去,有时却不行.我想这应该是多线程的问题..net默认禁止线程间互相内部调用.list是主线程的变量,打开异步后在子线程对其赋值,是不被允许的.但是我想不通的是为什么有时候却也能赋值成功.也许是我理解有误.如果哪位牛人看到了我的困惑,希望能对我指点一二.现在我对多线程还不甚了解.(汗一个~~~)

其实,个人认为,消息队列的应用范围还是比较有限的,首先,他只能是window系统,在.net下调用,然后,它对网络带宽要求比较高.所以在局域网内应用还是比较好的,在interent上的应用,其实有更好的解决方案:.net remoting与web services

Demo下载:

http://ljzforever.qupan.com/?folder=951925

参考的文章:

ASP.NET中进行消息处理(MSMQ)一

http://dev.yesky.com/178/8196178.shtml

ASP.NET中进行消息处理(MSMQ)二

http://dev.yesky.com/229/8196229.shtml

.net+msmq快速访问数据库

http://developer.ccidnet.com/art/322/20030214/37984_1.html

消息队列(Message Queue)简介及其使用

http://www.cnblogs.com/rickie/archive/2004/11/16/64345.html

msmq两个网域之间消息传输与接收测试总结

http://www.cnblogs.com/billqi/archive/2005/12/29/307371.html

MSMQ在ASP.NET中的应用问题?谢谢!

http://topic.csdn.net/t/20020829/11/979610.html

. Net环境下消息队列(MSMQ)对象的应用

http://www.cnblogs.com/rickie/archive/2004/11/17/64712.aspx

.net的MSMQ异步调用

http://www.wangchao.net.cn/bbsdetail_37204.html

使用MSMQ

http://myxq.cnblogs.com/archive/2005/03/15/119150.aspx

时间: 2024-08-03 11:32:46

PetShop 4.0学习笔记:消息队列MSMQ的相关文章

WCF分布式开发步步为赢(13):WCF服务离线操作与消息队列MSMQ

之前曾经写过一个关于MSMQ消息队列的文章:WCF分布式开发必备知识(1):MSMQ消息队列 ,当时的目的也是用它来作为学习WCF 消息队列MSMQ编程的基础文章.在那篇文章里,我们详细介绍了MSMQ消息队列的基本概念.安装.部署.开发.调试等相关问题.今天我们来学习WCF分布式开发步步为赢(13):WCF服务离线操作与消息队列MSMQ.在WCF框架下使用MSMQ消息队列服务编程.  这里我会给出一个使用WCF MSMQ实现离线请求的DEMO示例程序. 全文结构是:[1]MSMQ基本概念[2]W

微软消息队列MSMQ 传输异常的总结!

公司线上环境99%是esxi的虚拟环境,随着公司线上虚拟机的增加,在部署虚拟机时我们一般都是采用模板才统一部署,当一个模板建立好后,新建虚拟机时就默认采用该模版运行,没有加入用户自定义环节. 由于公司为软件型企业且百分之九十采用的是微软的.net开发用户平台,由于平台的特殊性需要和多方面机构进行数据交换工作,根据开发的环境特点,选用的是微软系统自带的消息队列MSMQ进行数据传输, 随着msmq服务器越来越多的上线,而且会多台服务器往一台服务器上发送消息,最近频繁的发现一个问题,服务器服务正常,各

微软企业库5.0学习笔记(10)ASP.NET模块依赖注入

您可以使用HTTP模块,一个到ASP.NET HttpApplicationState类的扩展,在Global.asax编写代码强制ASP.NET在每一个页面请求时自动注入依赖的对象,就像在ASP.NET Web窗体应用程序中讨论的一样. 下列方法显示了一个合适的方法能够获取PreRequestHandlerExecute事件将它自己注入到ASP.NET的执行流水线,在每个页面请求中通过容器的BuildUp方法运行Http模块,并获取OnPageInitComplete事件.当OnPageIni

一起学ASP.NET Core 2.0学习笔记(二): ef core2.0 及mysql provider 、Fluent API相关配置及迁移

不得不说微软的技术迭代还是很快的,上了微软的船就得跟着她走下去,前文一起学ASP.NET Core 2.0学习笔记(一): CentOS下 .net core2 sdk nginx.supervisor.mysql环境搭建搭建好了.net core linux的相关环境,今天就来说说ef core相关的配置及迁移: 简介: Entity Framework(以下简称EF) 是微软以 ADO.NET 为基础所发展出来的对象关系对应 (O/R Mapping) 解决方案,EF Core是Entity

Swift 2.0学习笔记(Day5)——我所知道的标识符和关键字

Swift 2.0学习笔记(Day5)--我所知道的标识符和关键字   原创文章,欢迎转载.转载请注明:关东升的博客 好多计算机语言都有标识符和关键字,一直没有好好的总结,就是这样的用着,现在小小的整理一下Swift中的标识符和关键字. 什么是标识符呢? 标识符就是给变量.常量.方法.函数.枚举.结构体.类.协议等由开发人员指定的名字. 其实,构成标识符的字母是有一定规范的,Swift中命名规则是: 区分大小写,Myname与myname是两个不同的标识符: 标识符首字符可以以下划线(_)或者字

Quartz.NET 2.0 学习笔记(1) :Quartz.NET简介

转自:http://www.cnblogs.com/lzrabbit/archive/2012/04/13/2447609.html Quartz.NET 项目地址 http://quartznet.sourceforge.net/ Quartz.NET 2.0 学习笔记(1) :Quartz.NET简介 Quartz.NET 2.0 学习笔记(2) :和1.0的几点不同 Quartz.NET 2.0 学习笔记(3) :通过配置文件实现任务调度 Quartz.NET 2.0 学习笔记(4) :c

Swift 2.0学习笔记(Day 29)——访问级别

Swift 2.0学习笔记(Day 29)——访问级别 原创文章,欢迎转载.转载请注明:关东升的博客 访问级别: Swift提供了3种不同访问级别,对应的访问修饰符为:public.internal和private.这些访问修饰符可以修饰类.结构体.枚举等面向对象的类型,还可以修饰变量.常量.下标.元组.函数.属性等内容. l public.可以访问自己模块中的任何public实体.如果使用import语句引入其他模块,我们可以访问其他模块中的public实体. l internal.只能访问自

Hadoop1.0.0学习笔记

Hadoop1.0.0学习笔记 一.  安装JDK,配置环境JAVA环境变量 exportJAVA_HOME=/home/ligang/jdk1.6.0_26 exportJRE_HOME=/home/ligang/jdk1.6.0_26/jre exportCLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH 二.  安装Hadoop-1.0.0 1.     下载hadoop文件,地址为:http://hadoop.apache.org/co

Swift 2.0学习笔记(Day 37)——默认构造函数

Swift 2.0学习笔记(Day 37)--默认构造函数原创文章,欢迎转载.转载请注明:关东升的博客 结构体和类的实例在构造过程中会调用一种特殊的init方法,称为构造函数.构造函数没有返回值,可以重载.在多个构造函数重载的情况下,运行环境可以根据它的外部参数名或参数列表调用合适的构造函数.默认构造函数结构体和类在构造过程中会调用一个构造函数,即便是没有编写任何构造函数,编译器也会提供一个默认的构造函数.下面看示例代码: class Rectangle { var width: Double