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

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

    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

     
  • 相关阅读:
    windows下使用C#获取特定进程网络流量
    .NET设计模式(9):桥接模式(Bridge Pattern)(转)
    .NET设计模式(8):适配器模式(Adapter Pattern)(转)
    .NET设计模式(7):创建型模式专题总结(Creational Pattern)(转)
    .NET设计模式(6):原型模式(Prototype Pattern)(转)
    .NET设计模式(5):工厂方法模式(Factory Method)(转)
    .NET设计模式(4):建造者模式(Builder Pattern)(转)
    .NET设计模式(3):抽象工厂模式(Abstract Factory)(转)
    单件模式(Singleton Pattern)(转)
    PowerDesigner(九)-模型文档编辑器(生成项目文档)(转)
  • 原文地址:https://www.cnblogs.com/sheseido/p/5544444.html
Copyright © 2011-2022 走看看