在上一篇我簡單介紹了MSMQ的相關概念,本篇將以代碼說明網絡
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);
消息(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隊列作了簡單的封裝,以下
咱們的用戶實體也很簡單,以下
下面咱們來建立一個隊列,如圖咱們成功的建立了"myqueue"隊列
下面咱們向隊列中發送消息。如圖,從圖右邊能夠看到消息成功被加入到隊列中
接着咱們採用Peek方法接收消息(即不移除MSMQ的對應消息),很顯然圖中的Message依然存在MSMQ隊列中
接着咱們採用Receive方法來接收消息。這個時候咱們能夠很明顯的看見MSMQ原來對應的消息被刪除了
最後讓我來測試,MSMQ的事務性。咱們先刪除咱們的隊列,在從新建立。咱們連續向隊列中插入5個消息,可是在插入第5個消息的時候咱們拋出異常,若是MSMQ支持事務的話那麼前面發送的4個Message將被回滾掉,MSMQ隊列中應該爲0個消息
另外值得注意的是,MSMQ的消息發送與接收,採用的是同步的方式。這樣假如咱們的消息隊列中一個消息都沒有,咱們調用Receive()去接收該隊列的消息會怎麼樣呢? 程序會被阻塞在這裏,直到消息隊列中有消息,程序纔會接着往下走。碰到這種狀況是很要命的,可是不怕MSMQ支持異步消息,因爲篇幅有限我就不在多少,這裏我給出一個異步操做的連接有興趣的朋友能夠去研究下,點擊 這裏