日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

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

發(fā)布時(shí)間:2024/9/20 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ASP.NET中进行消息处理(MSMQ) 二 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

在我上一篇文章《ASP.NET中進(jìn)行消息處理(MSMQ)一》里對(duì)MSMQ做了個(gè)通俗的介紹,最后以發(fā)送普通文本消息和復(fù)雜的對(duì)象消息為例介紹了消息隊(duì)列的使用。?本文在此基礎(chǔ)上繼續(xù)介紹MSMQ的相關(guān)知識(shí)點(diǎn),最后還是通過(guò)一個(gè)示例程序來(lái)分析MSMQ在實(shí)際項(xiàng)目開(kāi)發(fā)中的應(yīng)用。
建議:如果你對(duì)MSMQ不夠了解,在你閱讀本文前請(qǐng)先閱讀第一部分:《ASP.NET中進(jìn)行消息處理(MSMQ)一》。一、消息傳遞的優(yōu)先級(jí)
????? 在MSMQ中消息在隊(duì)列里傳輸是分有優(yōu)先級(jí)的,這里我就以實(shí)例的形式介紹下關(guān)于優(yōu)先級(jí)的使用,優(yōu)先級(jí)一共有七種,MessagePriority枚舉里全部進(jìn)行了封裝。因這里只作程序演示就不一一列舉出,僅用了Highest和Normal兩種類(lèi)型,關(guān)于消息隊(duì)列上進(jìn)行消息傳輸?shù)钠叻N優(yōu)先級(jí)大家可以參考我下面提供的MessagePriority枚舉源代碼定義。
????? 那么在發(fā)送消息的時(shí)候怎么指定消息的優(yōu)先級(jí)呢?在Message對(duì)象里封裝有一個(gè)屬性Priority,接受一個(gè)枚舉MessagePriority類(lèi)型的值來(lái)設(shè)置消息傳輸?shù)膬?yōu)先級(jí)。如下:

1System.Messaging.Message?message?=?new?System.Messaging.Message();
2message.Priority?=?MessagePriority.Highest;??//最高消息優(yōu)先級(jí)


??????下面來(lái)看看一個(gè)在消息傳輸中使用優(yōu)先級(jí)的示例程序,通過(guò)示例程序會(huì)學(xué)習(xí)得更明白。示例程序界面:


??????根據(jù)界面可知,提供了消息名字,消息優(yōu)先級(jí)和消息內(nèi)容三個(gè)輸入項(xiàng),前面曾經(jīng)說(shuō)過(guò),這里為了方便演示就僅用了Highest和Normal兩種類(lèi)型,當(dāng)點(diǎn)擊發(fā)送消息的時(shí)候就通過(guò)是否選擇優(yōu)先級(jí)來(lái)設(shè)置消息的優(yōu)先級(jí),代碼如下: ?1private?void?btnSend_Click(object?sender,?EventArgs?e)
?2{
?3????//連接到本地的專(zhuān)用隊(duì)列myQueue
?4????MessageQueue?myQueue?=?new?MessageQueue(".\\private$\\myQueue");
?5????System.Messaging.Message?message?=?new?System.Messaging.Message();
?6????message.Label?=?tbName.Text;
?7????message.Body?=?tbContext.Text;
?8
?9????if?(cbPriority.Checked)
10????{
11????????message.Priority?=?MessagePriority.Highest;
12????}
13????else
14????{
15????????message.Priority?=?MessagePriority.Normal;
16????}
17????myQueue.Send(message);
18????MessageBox.Show("成功發(fā)送消息到隊(duì)列");
19}

???? 這里我們可以向隊(duì)列里發(fā)送兩條消息,以便后面測(cè)試讀取方法,發(fā)送兩條消息到隊(duì)列,此時(shí),從隊(duì)列消息中可以看到:?


???? "刷新隊(duì)列"實(shí)質(zhì)上就是把隊(duì)列里的消息全部讀取出來(lái),具體的實(shí)現(xiàn)在《ASP.NET中進(jìn)行消息處理(MSMQ)一》里已經(jīng)作了詳細(xì)的介紹,這里就不在多說(shuō),看看下面的代碼: ?1private?void?DisplayMessage()
?2????????{
?3????????????//連接到本地隊(duì)列
?4????????????MessageQueue?myQueue?=?new?MessageQueue(".\\private$\\myQueue");
?5????????????myQueue.MessageReadPropertyFilter.Priority?=?true;
?6????????????DataTable?messageTable?=?new?DataTable();
?7????????????messageTable.Columns.Add("名字");
?8????????????messageTable.Columns.Add("消息內(nèi)容");
?9????????????messageTable.Columns.Add("優(yōu)先級(jí)");
10????????????XmlMessageFormatter?formatter?=?new?XmlMessageFormatter(new?string[]?{?"System.String"?});
11????????????try
12????????????{
13????????????????//從隊(duì)列中接收消息
14????????????????System.Messaging.Message[]?messages?=?myQueue.GetAllMessages();
15????????????????for?(int?index?=?0;?index?<?messages.Length;?index++)
16????????????????{
17????????????????????messages[index].Formatter?=?formatter;
18
19????????????????????string?label?=?messages[index].Label;
20????????????????????string?body?=?messages[index].Body.ToString();
21????????????????????string?priority?=?messages[index].Priority.ToString();
22
23????????????????????messageTable.Rows.Add(new?string[]?{?label,?body,?priority?});
24????????????????}
25????????????????this.dgvMessage.DataSource?=?messageTable;
26????????????}
27????????????catch?(MessageQueueException?e1)
28????????????{
29????????????????MessageBox.Show(e1.Message);
30????????????}
31????????}
32????}

????? 這里封裝了一方法,專(zhuān)門(mén)負(fù)責(zé)從隊(duì)列里讀取全部消息并綁定在DataGridView控件上,這里我們只需要在按扭Click事件里調(diào)用這方法就OK。

1private?void?btnRec_Click(object?sender,?EventArgs?e)
2{
3????DisplayMessage();
4}

???? 這就完成了給消息設(shè)置優(yōu)先級(jí)的消息傳輸?shù)膽?yīng)用,最終的測(cè)試結(jié)果如下:


注:要完成以上應(yīng)用還需注意一點(diǎn),由于消息的優(yōu)先級(jí)是枚舉類(lèi)型,在直接messages[index].Priority.ToString();這種方式來(lái)獲取優(yōu)先級(jí)轉(zhuǎn)化到字符串的時(shí)候,他需要一個(gè)過(guò)濾器(Filter),否則會(huì)拋出一個(gè)InvalidCastExceptionle類(lèi)型的異常,異常信息"接收消息時(shí)未檢索到屬性 Priority。請(qǐng)確保正確設(shè)置了 PropertyFilter。",要解決這問(wèn)題只需要把消息對(duì)象的MessageReadPropertyFilter(過(guò)濾器) 的Priority設(shè)置為true就OK了。見(jiàn)上面代碼里!^.^
MessagePriority枚舉源代碼定義詳細(xì)如下: ?1//?摘要:
?2//?????指定消息隊(duì)列在消息傳遞到隊(duì)列的過(guò)程中應(yīng)用于該消息的優(yōu)先級(jí),以及指定何時(shí)將消息插入目標(biāo)隊(duì)列。
?3public?enum?MessagePriority
?4{
?5????//?摘要:
?6????//?????最低消息優(yōu)先級(jí)。
?7????Lowest?=?0,
?8????//
?9????//?摘要:
10????//?????位于?Low?和?Lowest?消息優(yōu)先級(jí)之間。
11????VeryLow?=?1,
12????//
13????//?摘要:
14????//?????低消息優(yōu)先級(jí)。
15????Low?=?2,
16????//
17????//?摘要:
18????//?????普通消息優(yōu)先級(jí)。
19????Normal?=?3,
20????//
21????//?摘要:
22????//?????位于?System.Messaging.MessagePriority.High?和?System.Messaging.MessagePriority.Normal
23????//?????消息優(yōu)先級(jí)之間。
24????AboveNormal?=?4,
25????//
26????//?摘要:
27????//?????高消息優(yōu)先級(jí)。
28????High?=?5,
29????//
30????//?摘要:
31????//?????位于?Highest?和?High?消息優(yōu)先級(jí)之間。
32????VeryHigh?=?6,
33????//
34????//?摘要:
35????//?????最高消息優(yōu)先級(jí)。
36????Highest?=?7,
37}

二、事務(wù)性消息處理
????? 事務(wù)我想大家對(duì)這個(gè)詞應(yīng)該都不會(huì)陌生,在操作數(shù)據(jù)庫(kù)的時(shí)候經(jīng)常都會(huì)用到事務(wù),確保操作成功,要么全部完成(成功),要么全部不完成(失敗)。在MSMQ中利用事務(wù)性處理,可以確保事務(wù)中的消息按照順序傳送,只傳送一次,并且從目的隊(duì)列成功地被檢索。
?????那么,在MSMQ上使用事務(wù)性處理怎么實(shí)現(xiàn)呢?可以通過(guò)創(chuàng)建MessageQueueTransation類(lèi)的實(shí)例并將其關(guān)聯(lián)到MessageQueue組件的實(shí)例來(lái)執(zhí)行,執(zhí)行事務(wù)的Begin方法,并將其實(shí)例傳遞到收發(fā)方法。然后,調(diào)用Commit以將事務(wù)的更改保存到目的隊(duì)列。
???? 創(chuàng)建事務(wù)性消息和普通的消息有一點(diǎn)小小的區(qū)別,大家可從下圖上體會(huì)到:?


???? 通過(guò)代碼方式建立事務(wù)性消息隊(duì)列只在Create方法的參數(shù)上動(dòng)動(dòng)手腳就OK,詳細(xì)如下: 1//創(chuàng)建普通的專(zhuān)用消息隊(duì)列
2MessageQueue?myMessage?=?MessageQueue.Create(@".\private$\myQueue");
3//創(chuàng)建事務(wù)性的專(zhuān)用消息隊(duì)列
4MessageQueue?myTranMessage?=MessageQueue.Create(@".\private$\myQueueTrans",?true);


????? 啟動(dòng)了事務(wù),那么在發(fā)送和接收消息的時(shí)候肯定是與原來(lái)有一定的差別的,這里我就不做詳細(xì)介紹,下面給出示意性代碼,有興趣的朋友可以直接下載本文示例程序代碼了解更多。
普通的消息發(fā)送示意性代碼:

1//連接到本地的隊(duì)列
2MessageQueue?myQueue?=?new?MessageQueue(".\\private$\\myQueue");
3Message?myMessage?=?new?Message();
4myMessage.Body?=?"消息內(nèi)容";
5myMessage.Formatter?=?new?XmlMessageFormatter(new?Type[]?{?typeof(string)?});
6//發(fā)送消息到隊(duì)列中
7myQueue.Send(myMessage);

啟動(dòng)了事務(wù)后的消息發(fā)送示意性代碼:

?1//連接到本地的隊(duì)列
?2MessageQueue?myQueue?=?new?MessageQueue(".\\private$\\myQueueTrans");
?3
?4Message?myMessage?=?new?Message();
?5myMessage.Body?=?"消息內(nèi)容";
?6myMessage.Formatter?=?new?XmlMessageFormatter(new?Type[]?{?typeof(string)?});
?7
?8MessageQueueTransaction?myTransaction?=?new?MessageQueueTransaction();
?9//啟動(dòng)事務(wù)
10myTransaction.Begin();
11//發(fā)送消息到隊(duì)列中
12myQueue.Send(myMessage,?myTransaction);??//加了事務(wù)
13//提交事務(wù)
14myTransaction.Commit();
15Console.WriteLine("消息發(fā)送成功!");


讀取消息示意性代碼:

?1//連接到本地隊(duì)列
?2MessageQueue?myQueue?=?new?MessageQueue(".\\private$\\myQueueTrans");
?3myQueue.Formatter?=?new?XmlMessageFormatter(new?Type[]?{?typeof(string)?});
?4if?(myQueue.Transactional)
?5{
?6????MessageQueueTransaction?myTransaction?=?new?MessageQueueTransaction();
?7????//啟動(dòng)事務(wù)
?8????myTransaction.Begin();
?9????//從隊(duì)列中接收消息
10????Message?myMessage?=?myQueue.Receive(myTransaction);
11????string?context?=?myMessage.Body?as?string;?//獲取消息的內(nèi)容
12????myTransaction.Commit();
13????Console.WriteLine("消息內(nèi)容為:"?+?context);
14}

三、異步消息處理????? 在MSMQ中對(duì)消息的操作分有同步化操作和異步化操作兩種,那兩者到底有何區(qū)別呢?簡(jiǎn)單的說(shuō)同步化操作就是一項(xiàng)操作沒(méi)有完成前它將堵塞整個(gè)進(jìn)程直到操作完成,下一項(xiàng)操作才會(huì)執(zhí)行。所謂異步化操作則相反,不會(huì)堵塞啟動(dòng)操作的調(diào)用線程。如果你想在檢索消息但不想堵塞其他程序的執(zhí)行,則可使用異步消息處理。
???? 在MSMQ中異步接收消息使用BeginReceive方法和EndReceive方法來(lái)標(biāo)記操作的開(kāi)始和結(jié)束,異步查看消息則使用BeginPeek和EndPeek兩個(gè)方法來(lái)標(biāo)記異步讀取的開(kāi)始和結(jié)束。同時(shí),異步接收和查看消息還可以指定超時(shí)時(shí)間,關(guān)于這點(diǎn)我在后續(xù)文章里再做詳細(xì)的介紹,有興趣的朋友可以關(guān)注。
????? 這里我將使用《ASP.NET中進(jìn)行消息處理(MSMQ)一》一文里使用過(guò)的Book類(lèi)來(lái)作為消息傳輸,沒(méi)閱讀過(guò)的朋友請(qǐng)先閱讀這篇文章,了解Book類(lèi)的結(jié)構(gòu)。下面提供了一個(gè)示例,創(chuàng)建隊(duì)列和發(fā)送消息到隊(duì)列在前面我們已經(jīng)使用多次了這里就不貼代碼了,發(fā)送消息這里與第一篇文章中介紹如何發(fā)送一個(gè)復(fù)雜的類(lèi)型信息到隊(duì)列比,只是多了事務(wù)處理,詳細(xì)如下:

?1///?<summary>
?2///?發(fā)送消息到隊(duì)列
?3///?</summary>
?4private?static?void?SendMessage()
?5{
?6????MessageQueue?myQueue?=?new?MessageQueue(".\\private$\\myAsyncQueue");
?7????if?(myQueue.Transactional)
?8????{
?9????????Book?book?=?new?Book();
10????????book.BookId?=?1001;
11????????book.BookName?=?"ASP.NET";
12????????book.BookAuthor?=?"ZhangSan";
13????????book.BookPrice?=?88.88;
14????????Message?message?=?new?Message(book);
15????????message.Formatter?=?new?XmlMessageFormatter(new?Type[]?{?typeof(MSMQ.Async.Book)?});
16
17????????MessageQueueTransaction?myTransaction?=?new?MessageQueueTransaction();
18????????myTransaction.Begin();
19????????myQueue.Send(message,?myTransaction);
20????????myTransaction.Commit();
21????????Console.WriteLine("消息成功發(fā)送到隊(duì)列!");
22????}
23}


異步接收消息:

?1///?<summary>
?2///?異步接收消息
?3///?</summary>
?4private?static?void?AsyncReceiveMessage()
?5{
?6????MessageQueue?myQueue?=?new?MessageQueue(".\\private$\\myAsyncQueue");
?7????if?(myQueue.Transactional)
?8????{
?9????????MessageQueueTransaction?myTransaction?=?new?MessageQueueTransaction();
10????????//這里使用了委托,當(dāng)接收消息完成的時(shí)候就執(zhí)行MyReceiveCompleted方法
11????????myQueue.ReceiveCompleted?+=?new?ReceiveCompletedEventHandler(MyReceiveCompleted);
12????????myQueue.Formatter?=?new?XmlMessageFormatter(new?Type[]?{?typeof(MSMQ.Async.Book)?});
13????????myTransaction.Begin();
14????????myQueue.BeginReceive();//啟動(dòng)一個(gè)沒(méi)有超時(shí)時(shí)限的異步操作
15????????signal.WaitOne();
16????????myTransaction.Commit();
17????}
18} ?1private?static?void?MyReceiveCompleted(Object?source,?ReceiveCompletedEventArgs?asyncResult)
?2{
?3????try
?4????{
?5????????MessageQueue?myQueue?=?(MessageQueue)source;
?6????????//完成指定的異步接收操作
?7????????Message?message?=?myQueue.EndReceive(asyncResult.AsyncResult);
?8????????signal.Set();
?9????????Book?book?=?message.Body?as?Book;
10????????Console.WriteLine("圖書(shū)編號(hào):{0}--圖書(shū)名稱(chēng):{1}--圖書(shū)作者:{2}--圖書(shū)定價(jià):{3}",
11????????????book.BookId.ToString(),
12????????????book.BookName,
13????????????book.BookAuthor,
14????????????book.BookPrice.ToString());
15????????myQueue.BeginReceive();
16????}
17????catch?(MessageQueueException?me)
18????{
19????????Console.WriteLine("異步接收出錯(cuò),原因:"?+?me.Message);
20
21????}
22}

四、MSMQ在郵件發(fā)送程序中的應(yīng)用
??? ?在郵件程序的應(yīng)用中,實(shí)現(xiàn)發(fā)送郵件的方法有很多種,很多朋友都比較喜歡郵件發(fā)送組件(如:JMail),在.NET Framework里也給我們提供了發(fā)送郵件的類(lèi)StmpClient,位于System.Net下。我想很多朋友都曾用到過(guò)此類(lèi),如果說(shuō)是在一個(gè)小型的郵件應(yīng)用里,完全沒(méi)有使用MSMQ的必要,因?yàn)閿?shù)據(jù)量不大,直接處理就OK,這里我以郵件程序來(lái)說(shuō)只是出于對(duì)MSMQ應(yīng)用的介紹。說(shuō)實(shí)在的,我也不知道怎么才能把這個(gè)東東給介紹清楚,先看看一張圖吧!


????? 現(xiàn)在的需求是這樣的,有一個(gè)郵件發(fā)送客戶(hù)端(SendMail.aspx,界面效果如上圖所示)和一個(gè)郵件發(fā)送管理的服務(wù)端(MailServer.aspx),當(dāng)在SendMail.aspx里發(fā)送郵件的時(shí)候,我們不直接將其發(fā)到目標(biāo)地址去,而是將其發(fā)送到消息隊(duì)列,然后由MailServer.aspx來(lái)負(fù)責(zé)從消息隊(duì)列里讀取出郵件信息在將其發(fā)送到目標(biāo)地址。其實(shí)SendMail.aspx的職責(zé)就是完成把郵件信息發(fā)送到消息隊(duì)列,示意性代碼如下: ?1protected?void?btnSendMail_Click(object?sender,?EventArgs?e)
?2{
?3????//取出數(shù)據(jù)存入MailInfo對(duì)象
?4????MailInfo?info?=?new?MailInfo();
?5????info.Title?=?tbTitle.Text;
?6????info.Content?=?tbContent.Text;
?7????info.StmpServer?=?tbSmtpServer.Text;
?8????info.Sender?=?tbSender.Text;
?9????info.SenderPwd?=?tbSenderPwd.Text;
10????info.ReceiveAddress?=?tbReceive.Text;
11
12????if?(info?!=?null)
13????{
14????????CreateQueue();
15????????SendMessage(info);
16????}
17}

???? CreateQueue和SendMessage這兩個(gè)方法完成消息隊(duì)列的創(chuàng)建和發(fā)送信息到隊(duì)列,MailInfo類(lèi)封裝的是郵件的詳細(xì)信息(既郵件的屬性),詳細(xì)定義如下:?

封裝了郵件的屬性


????? 轉(zhuǎn)到郵件管理端(MailServer.aspx),他負(fù)責(zé)從消息隊(duì)列里讀取出郵件信息并把此郵件發(fā)送到目標(biāo)地址去。其實(shí)現(xiàn)很簡(jiǎn)單,說(shuō)直接點(diǎn)他也就是完成了兩項(xiàng)操作(從隊(duì)列讀消息、將消息發(fā)送到目的郵箱),從隊(duì)列讀取消息的代碼如下:

?1///?<summary>
?2///?連接消息隊(duì)列并從隊(duì)列中接收消息
?3///?</summary>
?4private?MailInfo?ReceiveMessage()
?5{
?6????MailInfo?info?=?null;
?7????//連接到本地隊(duì)列
?8????MessageQueue?myQueue?=?new?MessageQueue(".\\private$\\myMailQueue");
?9????myQueue.Formatter?=?new?XmlMessageFormatter(new?Type[]?{?typeof(MailInfo)?});
10????try
11????{
12????????if?(myQueue.Transactional)
13????????{
14????????????MessageQueueTransaction?myTransaction?=?new?MessageQueueTransaction();
15????????????//啟動(dòng)事務(wù)
16????????????myTransaction.Begin();
17????????????//從隊(duì)列中接收消息
18????????????Message?myMessage?=?myQueue.Receive(myTransaction);
19????????????info?=?myMessage.Body?as?MailInfo;?//獲取消息的內(nèi)容
20????????????myTransaction.Commit();
21????????????return?info;
22????????}
23
24????}
25????catch?(MessageQueueException?e)
26????{
27????????this.tdError.InnerText?=?e.Message;
28????}
29????return?info;
30}


????? 該方法(ReceiveMessage)返回的是從隊(duì)列里讀取到的郵件信息,本示例中只是做了讀一條信息的實(shí)現(xiàn),如果要把隊(duì)列里的全部信息讀出并發(fā)送到目的郵箱,可以參考我前面所介紹的相關(guān)知識(shí)點(diǎn)來(lái)實(shí)現(xiàn)。得到了郵件的詳細(xì)信息,我們就可以使用相應(yīng)的技術(shù)將這信息發(fā)送到目標(biāo)郵箱去,本示例中我采用的是.NET Framework里提供的SmtpClient類(lèi)來(lái)完成的郵件發(fā)送,關(guān)于SmtpClient類(lèi)的使用網(wǎng)上有相當(dāng)豐富的資料介紹,這里我就不做詳細(xì)的說(shuō)明,核心代碼如下:

?1protected?void?Button2_Click(object?sender,?EventArgs?e)
?2{
?3????if?(info?!=?null)
?4????{
?5????????SmtpClient?client?=?new?SmtpClient();
?6????????client.Host?=?info.StmpServer;
?7????????client.UseDefaultCredentials?=?false;
?8????????client.Credentials?=?new?NetworkCredential(info.Sender,?info.SenderPwd);
?9????????client.DeliveryMethod?=?SmtpDeliveryMethod.Network;
10
11????????MailMessage?message?=?new?MailMessage(info.Sender,?info.ReceiveAddress);
12????????message.Subject?=?info.Title;
13????????message.Body?=?info.Content;
14????????message.BodyEncoding?=?Encoding.UTF8;
15????????message.IsBodyHtml?=?true;
16
17????????try
18????????{
19????????????//發(fā)送郵件到目標(biāo)地址
20????????????client.Send(message);
21????????????this.tdSucces.InnerText?=?"郵件已成功發(fā)送到目標(biāo)地址:"?+?info.ReceiveAddress;
22????????}
23????????catch?(Exception?ex)
24????????{
25????????????this.tdError.InnerText?=?"發(fā)送失敗,失敗原因:"?+?ex.Message;
26????????}
27????}
28}


運(yùn)行后的效果圖如下:


????? 本文中的所有示例程序全部通過(guò)調(diào)試,能力有限,文中所介紹的不是很清楚,詳細(xì)可直接下載源代碼了解。本代碼包里也包含有第一篇文章里的全部示例程序代碼。
點(diǎn)擊連接下載示例程序代碼:示例程序代碼下載

總結(jié)

以上是生活随笔為你收集整理的ASP.NET中进行消息处理(MSMQ) 二的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。