Message Queuing(MSMQ)演練

一、前言

上一篇我們簡單介紹了MicroSoft Message Queuing(微軟消息隊列)的安裝、連接MSMQ要用到的類庫以及API。所以在本篇將在.NET程序中演練MSMQ。

二、演練開始

首先給大家展示演練項目的整體設計,比如我是使用WinForm+控制檯的形式演練,功能包括消息發送(Send)、隊列創建、消息獲取(Peek、Receive)、隊列刪除(Delete)等。

1.總覽

演練項目使用的是WinForm+控制檯的形式,左邊紅色區域中是我們要實現MSMQ管理的功能,右邊是我們需要創建的項目。

Queue:隊列

Plant:生產的消息數量

Send:向隊列發送消息,當隊列不存在時提示是否創建隊列。

Peek:使用Peek方式獲取隊列

Receive:使用Receive方式獲取隊列

Delete:刪除隊列

image

下面是動態效果圖,加載可能會慢一些。

image

2.創建MSMQDemo

此程序的功能主要包括隊列創建、刪除、消息發送。消息獲取將分別調用Peek、Receive程序。代碼都有相應的註釋,也比較容易理解。

下面上代碼,項目代碼可以帶Github上下載,文章底部也有下載鏈接

using MSMQDemo.Model;
using System;
using System.Diagnostics;
using System.Messaging;
using System.Windows.Forms;

namespace MSMQDemo
{
    /// <summary>
    /// @ desc:MSMQ演示用例,包括隊列的連接、驗證、創建、刪除、消息發送、接受。
    /// @ author:yz
    /// @ date:2017-10-10
    /// </summary>
    public partial class main : Form
    {

        // 操作類型 1:Peek 2:Receive
        public int type = 0;

        // 隊列地址
        public string queueputh = string.Empty;

        // 隊列名稱
        public string queuename = string.Empty;

        /// <summary>
        /// @ desc:主函數
        /// </summary>
        public main()
        {
            InitializeComponent();
        }

        /// <summary>
        /// @ desc:發送
        /// @ author:yz
        /// </summary>
        private void Send_Click(object sender, EventArgs e)
        {
            string queuename = Queue.Text;

            int count = trackBar.Value;

            try
            {
                if (string.IsNullOrEmpty(queuename))
                {
                    MessageBox.Show("請輸入隊列!");
                    return;
                }

                if (count == 0)
                {
                    MessageBox.Show("請設置發送數量!");
                    return;
                }

                string _QueuePath = string.Format(@".\private$\{0}", queuename);

                if (!MessageQueue.Exists(_QueuePath))
                {
                    if (MessageBox.Show(string.Format("隊列\"{0}\"不存在是否創建?", queuename), string.Format("創建隊列"), MessageBoxButtons.YesNo, MessageBoxIcon.None) == DialogResult.Yes)
                    {
                        // 創建隊列
                        MessageQueue.Create(_QueuePath);

                        if (MessageBox.Show(string.Format("隊列\"{0}\"成功,是否繼續發送數據?", queuename), string.Format("發送數據"), MessageBoxButtons.YesNo, MessageBoxIcon.None) != DialogResult.Yes)
                        {
                            return;
                        }
                    }
                    else
                    {
                        return;
                    }
                }

                // 開始生產數據

                for (int i = 0; i < count; i++)
                {
                    MessageQueue localQueue = new MessageQueue(_QueuePath);

                    System.Messaging.Message msg = new System.Messaging.Message()
                    {
                        Body = new KeyModel() { guid = Guid.NewGuid(), time = DateTime.Now },
                        Formatter = new XmlMessageFormatter(new Type[] { typeof(KeyModel) })
                    };

                    localQueue.Send(msg);
                }

                MessageBox.Show(string.Format("成功發送 {0} 條消息到\"{1}\"隊列!", count, queuename));
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

        }

        /// <summary>
        /// @ desc:使用Receive方式獲取隊列
        /// @ author:yz
        /// </summary>
        private void Receive_Click(object sender, EventArgs e)
        {
            if (verify(2))
            {
                Process.Start(Application.StartupPath + @"\Receive.exe", queuename);
            }
        }

        /// <summary>
        /// @ desc:使用Peek方式查看隊列
        /// @ author:yz
        /// </summary>
        private void Peek_Click(object sender, EventArgs e)
        {
            if (verify(1))
            {
                Process.Start(Application.StartupPath + @"\Peek.exe", queuename);
            }
        }

        /// <summary>
        /// @ desc:刪除隊列
        /// @ author:yz
        /// </summary>
        private void Delete_Click(object sender, EventArgs e)
        {
            if (verify(0))
            {
                if (MessageBox.Show(string.Format("確認刪除\"{0}\"隊列?", queuename), string.Format("刪除隊列"), MessageBoxButtons.YesNo, MessageBoxIcon.None) == DialogResult.Yes)
                {
                    MessageQueue.Delete(queueputh);

                    MessageBox.Show("刪除成功!");
                }
            }
        }

        /// <summary>
        /// @ desc:滑動條選擇發送數量
        /// @ author:yz
        /// </summary>
        private void trackBar_Scroll(object sender, EventArgs e)
        {
            label3.Text = trackBar.Value.ToString();
        }

        /// <summary>
        /// @ desc:驗證數據
        /// @ author:yz
        /// </summary>
        /// <param name="_type">類型</param>
        /// <returns></returns>
        private bool verify(int _type)
        {
            queuename = Queue.Text;

            if (string.IsNullOrEmpty(queuename))
            {
                MessageBox.Show("請輸入隊列!");
                return false;
            }

            type = _type; queueputh = string.Format(@".\private$\{0}", queuename);

            if (!MessageQueue.Exists(queueputh))
            {
                MessageBox.Show(string.Format("隊列\"{0}\"不存在!", queuename));
                return false;
            }

            return true;
        }

    }
}

3.Peek調用程序

using Peek.Model;
using System;
using System.Messaging;

namespace Peek
{
    /// <summary>
    /// @ desc:MSMQ演示用例,使用Peek方式接收隊列。
    /// @ author:yz
    /// @ date:2017-10-10
    /// </summary>
    class Program
    {
        // 隊列路徑
        private static string _QueuePath = string.Empty;

        /// <summary>
        /// @ desc:主函數
        /// </summary>
        static void Main(string[] args)
        {
            Console.WriteLine("MQPeek!");

            string queuename = Environment.GetCommandLineArgs()[1];

            Console.WriteLine(string.Format("You are using \"{0}\" Queue", queuename));
            _QueuePath = string.Format(@".\private$\{0}", queuename);

            ReceiveMessageByPeek<KeyModel>();
            Console.ReadKey();
        }

        /// <summary>
        /// @ desc: 驗證隊列 隊列不存在則創建
        /// @ author:yz
        /// </summary>
        private static bool VerifyQueue()
        {
            try
            {
                // 判斷隊列是否存在 不存在則創建
                if (!MessageQueue.Exists(_QueuePath))
                {
                    Console.WriteLine(string.Format("\"{0}\"隊列不存在", _QueuePath));
                    return false;
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                return false;
            }

            return true;
        }

        /// <summary>
        /// @ desc: 採用Peek方式查看消息
        /// @ author:yz
        /// </summary>
        public static void ReceiveMessageByPeek<T>(MessageQueueTransaction tran = null)
        {
            try
            {
                if (VerifyQueue())
                {
                    // 初始化消息隊列
                    MessageQueue localQueue = new MessageQueue(_QueuePath);
                    localQueue.Formatter = new XmlMessageFormatter(new Type[] { typeof(T) });

                    Message msg = localQueue.Peek();

                    Console.WriteLine(MSMQDemo.Tools.Json.GetJson((T)msg.Body));
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }
    }
}

4.Receive調用程序

using Receive.Model;
using System;
using System.Messaging;
using System.Threading;

namespace Receive
{
    /// <summary>
    /// @ desc:MSMQ演示用例,使用Receive方式接收隊列。
    /// @ author:yz
    /// @ date:2017-10-10
    /// </summary>
    class Program
    {
        // 隊列路徑
        private static string _QueuePath = string.Empty;

        // 消息隊列
        private static MessageQueue localQueue;

        /// <summary>
        /// @ desc:主函數
        /// </summary>
        static void Main(string[] args)
        {
            Console.WriteLine("MQReceive!");

            string queuename = Environment.GetCommandLineArgs()[1];

            Console.WriteLine(string.Format("You are using \"{0}\" Queue", queuename));

            _QueuePath = string.Format(@".\private$\{0}", queuename);

            ReceiveMessage<KeyModel>();

            Console.ReadKey();
        }

        /// <summary>
        /// @ desc: 驗證隊列 隊列不存在則創建
        /// @ author:yz
        /// </summary>
        private static bool VerifyQueue()
        {
            try
            {
                // 判斷隊列是否存在 不存在則創建
                if (!MessageQueue.Exists(_QueuePath))
                {
                    Console.WriteLine(string.Format("\"{0}\"隊列不存在", _QueuePath));
                    return false;
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                return false;
            }

            return true;
        }

        /// <summary>
        /// @ desc:接收消息
        /// @ author:yz
        /// </summary>
        private static void ReceiveMessage<T>(MessageQueueTransaction tran = null)
        {
            try
            {
                if (VerifyQueue())
                {
                    localQueue = new MessageQueue(_QueuePath);
                    localQueue.ReceiveCompleted += new ReceiveCompletedEventHandler(MessageReceived<T>);
                    localQueue.BeginReceive();
                    Console.ReadLine();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }

        /// <summary>
        /// @ desc:繼續接收消息
        /// @ author:yz
        /// </summary>
        private static void MessageReceived<T>(object source, ReceiveCompletedEventArgs asyncResult)
        {
            bool isReceivedSucceed = true;

            try
            {
                //連接到隊列
                Message m = localQueue.EndReceive(asyncResult.AsyncResult);
                m.Formatter = new XmlMessageFormatter(new Type[] { typeof(T) });

                //顯示處理的消息.
                //Console.WriteLine(MSMQDemo.Tools.Json.GetJson((T)m.Body));

                ThreadPool.QueueUserWorkItem(new WaitCallback(InvokeMDAO<T>), m.Body);
            }
            catch (MessageQueueException)
            {
                isReceivedSucceed = false;
            }
            catch (Exception ex)
            {
                isReceivedSucceed = false;
                Console.WriteLine(ex.Message);
            }
            finally
            {
                if (isReceivedSucceed)
                {
                    localQueue.BeginReceive();
                }
            }
        }

        /// <summary>
        /// @ desc:接收回調
        /// @ author:yz
        /// </summary>
        private static void InvokeMDAO<T>(object state)
        {
            try
            {
                Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss  :") + MSMQDemo.Tools.Json.GetJson((T)state));
            }
            catch (Exception)
            {

                throw;
            }
        }
    }
}

Github:MSMQDemo

相關

Message Queuing(MSMQ)

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章