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)

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