(转)MSMQ续

原文做者:虔诚者    点此传送至原文html

上一篇我简单介绍了MSMQ的相关概念,本篇将以代码说明网络

Message

    Message是MSMQ的数据存储单元,咱们的用户数据通常也被填充在Message的body当中,所以很重要,让咱们来看一看其在.net中的体现,如图:异步

    在图上咱们能够看见,Message提供了三个构造函数,参数body表示咱们的用户数据,当咱们在构造函数中传入,数据最终会被赋值给其同名属性body,参数formatter对应同名属性Formatter,它是一个序列化器,当咱们的用户数据是一个复杂类型,好比类的时候Message会自动采用该序列化器将咱们的复杂类型序列化。message支持3种序列化对象:函数

-- XMLMessageFormatter对象----MessageQueue组件的默认格式化程序设置。测试

-- BinaryMessageFormatter对象;spa

-- ActiveXMessageFormatter对象;.net

    因为后二者格式化后的消息一般不能为人阅读,因此咱们常常用到的是XMLMessageFormatter对象。该对象构造方法有三种重载:3d

public XmlMessageFormatter(); 
public XmlMessageFormatter(string[] targetTypeNames); 
public XmlMessageFormatter(Type[] targetTypes);

MSMQ队列

      消息(Message)须要保存在msmq队列中,.net中采用System.Messaging.MessageQueue来管理MSMQ队列,它提供能操做MSMQ的绝大多数API,好比code

     1.判断指定路径的队列是否存在。其中path表明队列的路径,表示形式为"主机名\队列名称",例如:".\private$\myQueue",其中"."表明本地主机,"\private$\myQueue"则表明队列的名称,"private$"表示咱们建立的是专用队列,在网络上咱们能够经过路径来惟一肯定一个队列。orm

public static bool Exists(string path);

     2.建立队列。path表明队列的路径,transactional表示是否建立事务队列,默认为fasle。关于事务队列我在上一篇作了详细的论述,这里不在重复。

public static MessageQueue Create(string path);
public static MessageQueue Create(string path, bool transactional);

    3.删除队列

public static void Delete(string path);

    4.发送消息到MSMQ。obj表明咱们的用户数据,transation表示将咱们的发送操做归入事务当中。在前面咱们说过MSMQ接收的是Message,可是在这里咱们看到Send操做并未强制要求咱们采用Message类型参数。这是由于当我传入一个Object参数数据时,在Send操做的内部自动的给咱们建立了一个Message消息对象,而且将咱们的传入的Object参数采用默认的序列化器序列化,而后装入Message的body属性当中,若是咱们在Send方法中指定label属性,它将被赋值给Message的同名Label属性。固然咱们彻底能够自定义一个message对象传入Send方法中

public void Send(object obj);
public void Send(object obj, MessageQueueTransaction transaction);
public void Send(object obj, string label);

    5.接收消息。同理接收消息也能够被归入事务当中,采用Receive方法在取MSMQ的消息时,若是成功,会把MSMQ的对应消息给删除掉,而且只能取到消息队里中的排队头的消息。

public Message Receive();
public Message Receive(MessageQueueTransaction transaction);
public Message Receive(TimeSpan timeout);

    若是咱们想取指定标识的消息,就的采用以下的方法了,id表明消息的惟一标示。

public Message ReceiveById(string id);
public Message ReceiveById(string id, MessageQueueTransaction transaction);

   若是咱们在接收消息的后,不想把MSMQ队列中的消息删除怎么办呢?那么采用下面的方法吧,由于这两个方法接收MSMQ的消息,不会删除MSMQ中对应的消息,因此他们不支持事务,即没有提供事务的参数。

public Message Peek();
public Message PeekById(string id);

   咱们也能够一次性吧队列里面的全部消息取出来

public Message[] GetAllMessages();

实例 

    说了这么多,下面让咱们来代码实战一下,咱们采用控制台程序作测试,我把MSMQ队列作了简单的封装,以下

  View Code

咱们的用户实体也很简单,以下

  View Code

下面咱们来建立一个队列,如图咱们成功的建立了"myqueue"队列

  View Code

下面咱们向队列中发送消息。如图,从图右边能够看到消息成功被加入到队列中

  View Code

接着咱们采用Peek方法接收消息(即不移除MSMQ的对应消息),很显然图中的Message依然存在MSMQ队列中

  View Code

接着咱们采用Receive方法来接收消息。这个时候咱们能够很明显的看见MSMQ原来对应的消息被删除了

  View Code

    最后让我来测试,MSMQ的事务性。咱们先删除咱们的队列,在从新建立。咱们连续向队列中插入5个消息,可是在插入第5个消息的时候咱们抛出异常,若是MSMQ支持事务的话那么前面发送的4个Message将被回滚掉,MSMQ队列中应该为0个消息

  View Code

 

     另外值得注意的是,MSMQ的消息发送与接收,采用的是同步的方式。这样假如咱们的消息队列中一个消息都没有,咱们调用Receive()去接收该队列的消息会怎么样呢? 程序会被阻塞在这里,直到消息队列中有消息,程序才会接着往下走。碰到这种状况是很要命的,可是不怕MSMQ支持异步消息,因为篇幅有限我就不在多少,这里我给出一个异步操做的连接有兴趣的朋友能够去研究下,点击 这里 

相关文章
相关标签/搜索