新聞中心
使用 P2PMessageQueue

為企業(yè)提供網(wǎng)站設(shè)計、成都網(wǎng)站設(shè)計、網(wǎng)站優(yōu)化、全網(wǎng)整合營銷推廣、競價托管、品牌運營等營銷獲客服務(wù)。創(chuàng)新互聯(lián)公司擁有網(wǎng)絡(luò)營銷運營團隊,以豐富的互聯(lián)網(wǎng)營銷經(jīng)驗助力企業(yè)精準獲客,真正落地解決中小企業(yè)營銷獲客難題,做到“讓獲客更簡單”。自創(chuàng)立至今,成功用技術(shù)實力解決了企業(yè)“網(wǎng)站建設(shè)、網(wǎng)絡(luò)品牌塑造、網(wǎng)絡(luò)營銷”三大難題,同時降低了營銷成本,提高了有效客戶轉(zhuǎn)化率,獲得了眾多企業(yè)客戶的高度認可!
本部分,您將看到使用 P2PMessageQueue 類和相關(guān)類型的示例。
注 當運行該示例時,可以選擇部署到 Windows CE 或 Pocket PC 2003 模擬器或設(shè)備。您可以在不進行修改的情況下在任一個平臺上調(diào)試該項目(并運行該應(yīng)用程序)。運行示例時,看到的第一個屏幕提示您在閱讀器進程和發(fā)送器進程間進行選擇。無論選擇哪一個,都必須再次運行 .exe 文件(從 Program Files),然后選擇另一個選項。在 Pocket PC 平臺上,無論是使用模擬器還是設(shè)備,都必須重命名 .exe 文件(否則將激活現(xiàn)有的運行中應(yīng)用程序)。
字符串的簡單 IPC 交換
首先使用托管進程將字符串傳入另一個 .NET Compact Framework 應(yīng)用程序(也可以使發(fā)送方或接收方成為本機應(yīng)用程序。有三種不同的方法用來讀取接收端的字符串(相同的原理也適用于發(fā)送端):阻塞、非阻塞以及事件驅(qū)動。
發(fā)送方和接收方的圖形用戶界面 (GUI) 在功能方面是自描述性的,如圖 3、4 和 5 所示。
圖 3. 主窗體
圖 4. 讀取端
當發(fā)送方單擊 Send 按鈕時,發(fā)送一個字符串(如文本框中輸入的),并可以選擇將該消息設(shè)置為警告消息(基于 Message Is Alert 復選框狀態(tài))。發(fā)送方會阻塞,直到針對指定超時發(fā)送該消息(作為 combobox 中選擇的發(fā)送方)。位于該復選框下面的窗體底部顯示 Send 方法的返回結(jié)果,如圖 5 所示(即 OK)。
圖 5. 發(fā)送 / 編寫端
這里再次使用了下載示例中的 Send 方法。
- private void cmdSend_Click(object sender, System.EventArgs e) {
- Message msg;
- msg = new Message(
- System.Text.Encoding.ASCII.GetBytes(txtSend.Text),
- chkIsAlert.Checked);
- ReadWriteResult rwr = mQue.Send(msg, mTimeout);
- lblSendResult.Text = rwr.ToString();
- }
當閱讀器收到一個消息后,會將它顯示在列表視圖(第三列)中,并指出它是否是警告消息(第二列)。當成功接收到該消息時,第一列將始終顯示 OK。默認情況下,要接收一個消息,請單擊 Receive 按鈕;如果沒有消息要接收或者方法失敗,則列表視圖的第一列將指出原因(另兩列在該情形中不適用)。
在讀取和發(fā)送時,Queue Info 菜單(單擊 Info,然后單擊 Queue Info)會顯示有關(guān)隊列的數(shù)據(jù)。接收端上的 Mode 菜單(單擊 Read,然后單擊 Mode)有三個菜單項:On Demand Only、Event driven 和 Block a Thread。這些項用于配置該程序如何接收隊列外的消息。當您選擇一個模式后,它在示例應(yīng)用程序的生命周期內(nèi)不應(yīng)該更改(開發(fā)人員可針對自己的設(shè)計進行混合與匹配)。以下幾個小節(jié)描述三種讀取模式。
按命令讀(對應(yīng)于菜單 On Demand Only )
當接收方單擊 Receive 按鈕時,將執(zhí)行以下方法。
- private void cmdReceive_Click(object sender, System.EventArgs e) {
- Message msg;
- msg = new Message();
- // mTimeout is set by the end user by means of the GUI
- // to DON'T BLOCK (0), BLOCK (-1), or a real timeout value
- ReadWriteResult rwr = mQue.Receive(ref msg, mTimeout);
- ListViewItem lvi;
- if (rwr == ReadWriteResult.OK){
- bool isAlrt;
- string payload;
- isAlrt = msg.IsAlert;
- byte[] bytes = msg.MessageBytes;
- payload = System.Text.Encoding.ASCII.GetString(
- bytes, 0, bytes.GetLength(0));
- lvi = new ListViewItem(
- new string[]{rwr.ToString(), isAlrt.ToString(), payload});
- }else{
- lvi = new ListViewItem(
- new string[]{rwr.ToString(), @"n\a", @"n\a"});
- }
- listView1.Items.Add(lvi);
- listView1.Columns[2].Width = -2;}
事件驅(qū)動
事件驅(qū)動模型基本上意味著應(yīng)用程序不會在任意時刻通過調(diào)用 Receive(例如,在計時器上或者要求用戶單擊 Receive 按鈕)來輪詢新消息,相反,應(yīng)用程序會訂閱并捕獲來自 P2PMessageQueue 類的事件。要訂閱事件,需要使用正規(guī)的 .NET Compact Framework 委托習語(隊列的創(chuàng)建也不例外)。
- mQue = new P2PMessageQueue(
- isReader, txtQueueName.Text, maxL, maxM, out firstTime);
- mQue.DataOnQueueChanged += new EventHandler(mQue_DataOnQueueChanged);
引發(fā)該事件會調(diào)用方法,在本例中,只調(diào)用現(xiàn)有的接收方法。
- private void mQue_DataOnQueueChanged(object sender, EventArgs e) {
- this.Invoke(new EventHandler(this.cmdReceive_Click));
- }
阻塞線程
第三種從隊列進行讀取的方法是:創(chuàng)建一個線程,并使其阻塞以等待隊列的 Receive 方法。每次接收到消息時,應(yīng)用程序都會處理它,然后再次循環(huán)回阻塞。以下是一些帶有解釋的示例代碼。
您會在某個地方創(chuàng)建并啟動以下線程。
- Thread t = new Thread(new ThreadStart(ThreadBlockedOnRead));
- t.Start();
該線程用下面的方法運行。(有關(guān)更多上下文,請下載代碼)。
- private void ThreadBlockedOnRead(){
- while (mMode == 2){ // Thread mode
- Message msg = new Message();
- //Can actually omit a timeout for a true infinite block
- ReadWriteResult rwr = mQue.Receive(msg, 60 * 1000);
- if (rwr == ReadWriteResult.InvalidHandle || mMode != 2){
- return;
- }
- string body = rwr.ToString();
- if (rwr == ReadWriteResult.OK){
- byte[] bytes = msg.MessageBytes;
- string bytesAsString =
- System.Text.Encoding.ASCII.GetString(
- bytes, 0, bytes.GetLength(0));
- body += " | " + msg.IsAlert.ToString() + " | " + bytesAsString;
- }
- MessageBox.Show(body, "To terminate this mode use the menu again");
- }
- }
基本示例代碼至此結(jié)束。讀取隊列的三種方式也可以應(yīng)用于通過隊列發(fā)送。當事件接收到信號時(即,隊列從已滿轉(zhuǎn)變?yōu)槲礉M),可進行阻塞和發(fā)送或嘗試在不進行阻塞的情況下隨時進行發(fā)送。在下一部分中,您將看到該設(shè)計如何允許隊列中的消息包含其他結(jié)構(gòu) — 而不僅僅是字符串。
注 在開發(fā)一個依賴事件信號來識別隊列從已滿轉(zhuǎn)變?yōu)槲礉M的應(yīng)用程序時,需要在應(yīng)用程序啟動時針對隊列執(zhí)行一個初始寫入操作。如果不執(zhí)行該初始寫入操作,則應(yīng)用程序永遠不會開始寫入,因為該初始寫入操作必須經(jīng)過特定地執(zhí)行才能填充轉(zhuǎn)變?yōu)槲礉M狀態(tài)的隊列,因此,向事件發(fā)出信號以觸發(fā)針對該隊列的進一步寫入操作。
發(fā)送和接收更復雜的類型(不僅僅是字符串)
在前幾部分中,是在應(yīng)用程序之間傳遞字符串,但如果可以將字符串與字節(jié)數(shù)組進行轉(zhuǎn)換,則還可以傳遞任何數(shù)據(jù)類型。因此,將該類型轉(zhuǎn)換為一個字節(jié)數(shù)組,在其中創(chuàng)建 Message 類,然后發(fā)送 Message。在接收端,檢索 Message,獲取字節(jié)數(shù)組,然后在其中創(chuàng)建該類型(例如,公開類型的 ToBytes 和 FromBytes 方法)。另一個方法是,從 Message 類繼承自己的類,并在其中實現(xiàn)轉(zhuǎn)換。很自然,如果您嘗試傳遞一個復雜的對象圖,則在類型與字節(jié)數(shù)組之間進行轉(zhuǎn)換會難得多。嘗試使用沒有源代碼的類型需要特別注意,因為您可能不具有對該類型的完整狀態(tài)(例如,私有成員)的訪問權(quán),因此,可能無法準確地在類型與字節(jié)數(shù)組之間進行轉(zhuǎn)換。
出于簡單的目的,假設(shè)將一個 Int64 和一個 Boolean 從一個進程傳遞到另一個進程。將創(chuàng)建一個 CustomMessage 類,如下所示。
- public class CustomMessage : Message {
- public long TotalMemory;
- public bool AfterGC;
- public CustomMessage(){
- TotalMemory = 0;
- AfterGC = false;
- }
- public CustomMessage(long totMem, bool afterGarbCol){
- TotalMemory = totMem;
- AfterGC = afterGarbCol;
- }
- public override byte[] MessageBytes {
- get {
- byte[] b1 = BitConverter.GetBytes(TotalMemory);
- byte[] b2 = BitConverter.GetBytes(AfterGC);
- byte[] b = new byte[9];
- Buffer.BlockCopy(b1, 0, b, 0, 8);
- Buffer.BlockCopy(b2, 0, b, 8, 1);
- return b;
- }
- set {
- TotalMemory = BitConverter.ToInt64(value, 0);
- AfterGC = BitConverter.ToBoolean(value, 8);
- base.MessageBytes = value;
- }
- }
- }
添加了兩個感興趣的字段(TotalMemory、AfterGC),重寫 MessageBytes 屬性以實現(xiàn)轉(zhuǎn)換(get 和 set 方法位于轉(zhuǎn)換發(fā)生的位置),然后添加一個默認的構(gòu)造函數(shù)(這個參數(shù)化的構(gòu)造函數(shù)是可選的)。
現(xiàn)在,如果要使用前面的示例,只需更改兩處地方:
發(fā)送消息時,要創(chuàng)建一個 CustomMessage,而不是將值賦給 TotalMemory 和 AfterGC。
- //msg = new Message(. . .); //Instead of this line
- msg = new CustomMessage(GC.GetTotalMemory(false), false);
- ReadWriteResult rwr = mQue.Send(msg, mTimeout);
接收消息時,要創(chuàng)建一個 CustomMessage。
- //msg = new Message();
- msg = new CustomMessage(); //msg still declared as Message
- ReadWriteResult rwr = mQue.Receive(msg, mTimeout);
然后,在 mQue.Receive 返回時讀取它的屬性。
- //byte[] bytes = msg.MessageBytes;
- //payload = System.Text.Encoding.ASCII.GetString(. . .);
- payload = "Total Memory = " + ((CustomMessage)msg).TotalMemory.ToString() +
- (((CustomMessage)msg).AfterGC ? " after a GC" : " without forcing a GC");
【編輯推薦】
- 點對點消息隊列函數(shù):用于WinCE的IPC機制
- ASP.NET中無Cookie會話的優(yōu)點與缺點
- 無Cookie會話的實現(xiàn)
- ASP.NET Cookie:不是問題的問題
- .NET框架中的XML:XmlSerializer的內(nèi)部原理
分享名稱:P2PMessageQueue的實際用法
分享網(wǎng)址:http://m.5511xx.com/article/dpdohog.html


咨詢
建站咨詢
