WPF消息队列示例——结合项目经验

  标题是有些奇怪,WPF消息队列,消息队列的使用和WPF或者WinForm有关系吗?哦,没有,当然没有。只是我没有用过WPF,因此打算用WPF写这个DEMO。后半年的项目和微软消息队列练习非常紧密,整个项目的数据处理都是采用消息队列传输的。在做项目总结之前,打算回顾一下消息队列简单的使用,具体项目中的应用下一篇在写。

一、消息队列的简介

首先消息队列是要安装的,如果不了解,请度娘或谷哥之。MSMQ采用异步传输,可传输如文本、声音、图象等等。简单说一下我对消息队列的理解吧,就像开奥运会,站了很多队伍(美国队、中国队),这个就类似于队列;而中国队中具体的张三李四王五,就类似于队列中的消息。消息是可以独立存在,但是它在发送的时候,必须依附于某个队列。

其次,安装完消息队列之后,可以看到“传出队列”和“专用队列”。传出队列显示了,将要往外传输的消息的状态;专用队列,显示了已经接受的消息队列的状态。

如上图,左边的Client端产生了数据,数据以消息队列的方式发送出去。如果网络正常联通,则右边的专用队列会立刻接收到消息,消息会不断的累积在专用队列中。Server端接受处理消息之后,专用队列中的消息就会相应的减少。从上图及分析可以看出来,MSMQ是比较适合做分布式系统处理的。

二、一个简单的WPF示例

a、新建一个WPF的工程,拖拽控件如下图:

b、然后新增两个文件“Book.cs”和“MsgQueue.cs”。前者主要是定义了含有四个四段的book类;后者主要包含了三个方法:创建新队列CreateQueue()、发送消息SendMess()、接受消息ReveiceMess()。

具体代码如下:

Book:

View Code
*
 * to define Book class,five property
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MSMQDemo
{
    public class Book
    {
        private int _BookId;
        public int BookId
        {
            get { return _BookId; }
            set { _BookId = value; }
        }

        private string _BookName;
        public string BookName
        {
            get { return _BookName; }
            set { _BookName = value; }
        }

        private string _BookAuthor;
        public string BookAuthor
        {
            get { return _BookAuthor; }
            set { _BookAuthor = value; }
        }

        private double _BookPrice;
        public double BookPrice
        {
            get { return _BookPrice; }
            set { _BookPrice = value; }
        }

    }
}

MsgQueue:

View Code
/*
 * MsgQueue:包含了创建、发送、接收三个队列方法
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Messaging;
using System.Windows.Forms;

namespace MSMQDemo
{
    /// <summary>
    /// MsgQueue类,主要用于构造消息队列
    /// </summary>
    public class MsgQueue
    {
        /// <summary>
        /// 创建消息队列
        /// </summary>
        /// <param name="quePath"></param>
        public static void CreateQueue(string quePath)
        {
            try
            {
                if (!MessageQueue.Exists(quePath))
                {
                    MessageQueue.Create(@".\private$\myQueue");
                    MessageBox.Show("创建队列成功!");
                }
                else
                {
                    MessageBox.Show(quePath + "队列已创建,请勿重复创建!");
                }
            }
            catch (MessageQueueException ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        /// <summary>
        /// 链接并且发送消息队列
        /// </summary>
        /// <param name="book"></param>
        public static bool SendMess(Book book)
        {
            bool flag = false;

            try
            {
                MessageQueue myQueue = new MessageQueue(@".\private$\myQueue");
                System.Messaging.Message message = new System.Messaging.Message();
                message.Body = book;
                message.Formatter = new XmlMessageFormatter(new Type[] { typeof(Book) });
                myQueue.Send(message);
                flag = true;
            }
            catch (ArgumentException ex)
            {
                MessageBox.Show(ex.Message);
            }
            return flag;
        }

        /// <summary>
        /// 接收消息队列
        /// </summary>
        public static string ReveiceMess()
        {
            MessageQueue myQueue = new MessageQueue(@".\private$\myQueue");
            myQueue.Formatter = new XmlMessageFormatter(new Type[] { typeof(Book) });

            try
            {
                System.Messaging.Message mess = myQueue.Receive();
                Book book = (Book)mess.Body;
                return string.Format("编号:{0},书名:{1},作者:{2},定价:{3}", book.BookId, book.BookName, book.BookAuthor, book.BookPrice);

            }
            catch (MessageQueueException ex)
            {
                MessageBox.Show(ex.Message);
            }
            catch (InvalidCastException ex)
            {
                MessageBox.Show(ex.Message);
            }
            return "";
        }
    }
}

c、在WPF中的调用:

由于MsgQueue中的方法都是静态的,因此在WPF后来可以直接进行调用。

代码如下:

View Code
 /// <summary>
        /// 创建消息队列
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, RoutedEventArgs e)
        {
            MsgQueue.CreateQueue(@".\private$\"+textBox1.Text.Trim().ToString());
        }

        /// <summary>
        /// 发送队列
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, RoutedEventArgs e)
        {
            Book book = new Book();
            book.BookId = int.Parse(textBox2.Text.ToString());
            book.BookName = textBox3.Text;
            book.BookAuthor = textBox4.Text;
            book.BookPrice = double.Parse(textBox5.Text.ToString());
            if (MsgQueue.SendMess(book))
            {
                MessageBox.Show("成功发送消息到队列");
            }
        }

        private void ReveiceBtn_Click(object sender, RoutedEventArgs e)
        {
            this.textBox6.Text = MsgQueue.ReveiceMess();
        }

 最终演示效果:

三、扩展及代码下载

a、三种消息发送的格式

.NET消息队列提供了如下的格式程序:XmlMessageFormatter  ,BinaryMessageFormatter   ,ActiveXMessageFormatter 。上面的例子中,使用的是XmlMessageFormatter 。  

类型 特性
XmlMessageFormatter  这是默认的格式化程序,前面的例子都是使用它的,从这个名称我们就可以联想到,它是会将自定义的类型串行化为一个XML表示,这个格式化程序很慢,并且会创建相对较多的消息。然而,这些消息可以被运行在不同平台下的应用程序共享和理解。
BinaryMessageFormatter   这个格式化应用程序会把自定义类型串行化为一个专有的二进制的格式。他比上面一种的速度要快得多,而且生成的消息很紧凑。然而只有运行在.NET中的接收者才可以容易地解析这个消息的内容。
ActiveXMessageFormatter   ActiveXMessageFormatter   和BinaryMessageFormatter一样,他会把自定义的类型串行化为专用的二进制格式。这个格式也就是MSMQ的COM组件使用的格式。这些传统的COM组件为COM语言(比如Visual Basic 6)提供了基于MSMQ的功能。因此,您可以在用Visual Basic 6编写的MSMQ应用程序中使用这个格式化程序来发送消息或接收消息。

b、代码下载,点击这里

c、在分布式系统中的使用

微软petshop宠物商店用到了消息队列,有兴趣的也可以自行下载看看。

本篇参考了,http://www.cnblogs.com/beniao/archive/2008/06/26/1229934.html

原文地址:https://www.cnblogs.com/xiajf/p/MSMQ.html