使用 Visual C# 写入 Microsoft 消息队列并从中读取

本文介绍如何在 Visual C# 中 (MSMQ) 写入 Microsoft 消息队列并从中读取消息队列。

原始产品版本: Microsoft 消息队列
原始 KB 编号: 815811

在此任务中

摘要

本文介绍了以下内容:

  • 如何在 Windows 应用程序中创建消息并将其发送到 MSMQ。
  • 如何从专用队列中读取和反序列化要显示的消息内容。

要求

以下项目介绍了推荐的硬件、软件、网络基础结构、技能和知识以及所需的 Service Pack:

  • 以下安装了 MSMQ 的操作系统之一, (它作为选项包含在四个操作系统) :Windows 2000 Professional (或 Server) ,或 Windows XP Professional (或 Server) 。

本文还假定你熟悉以下内容:

  • MSMQ
  • 使用命令提示符中的工具

返回到顶部

写入 MSMQ 并从中读取

System.Messaging.NET Framework中的命名空间包含必须从中读取和写入 MSMQ 的类。 若要创建一个模拟在线帐单支付系统的小型 Windows 应用程序,请执行以下步骤:

  1. 打开 Visual Studio .NET 或 Visual Studio 2005。

  2. 在 Visual C# 中创建新的 Windows 应用程序,然后将其命名为 MSMQ

  3. 若要在未显示解决方案资源管理器时显示,请按 CTRL+ALT+L。 在“解决方案资源管理器”中,右键单击“引用”,然后单击“添加引用”

  4. “.NET ”选项卡上,选择 .dll 文件列表中的 System.Messaging.dll 文件。 单击 “选择”,然后单击“ 确定”。

    注意

    在 Visual Studio 2005 中,单击 DLL 列表中的 System.Messaging.dll 文件,然后单击“ 确定”。

  5. Form1.cs 在“设计”视图中打开。 如果未打开,请双击解决方案资源管理器中的Form1.cs

  6. 按 CTRL+Alt+X 打开工具箱。 在“工具箱”中,单击“Windows 窗体”选项卡。

  7. “工具箱”中,将以下内容拖动到 Form1 的中间:

    • 标签和文本框各有四行 (放置在每个标签) 的右侧。
    • 在标签和文本框下,将两个按钮控件拖到 Form1 上。
  8. 右键单击控件,单击“ 属性”,然后将标签的 Text 属性设置为以下 (,以便) :

    • 支付给:
    • 您的姓名:
    • 量:
    • 截止日期:
  9. 在“ 属性 ”对话框中,将 button1 的 Text 属性设置为 “发送付款”,并将 button2 的 Text 属性设置为 “处理付款”。

  10. 此应用程序适用于必须首先在计算机管理控制台中创建的专用队列。 为此,请按照下列步骤操作:

    1. 在桌面上,右键单击“ 我的电脑”,然后单击“ 管理”。
    2. 展开“ 服务和应用程序” 节点以查找 MSMQ。

    注意

    如果未找到 MSMQ,则不会安装它。

  11. 展开 “消息队列”,右键单击“ 专用队列”,指向 “新建”,然后单击“ 专用队列”。

  12. 在“ 队列名称 ”框中,键入 billpay,然后单击“ 确定”。

    注意

    不要选中“事务检查”框。 使计算机管理控制台保持打开状态,因为稍后会返回到该控制台查看消息。

  13. Form1 代码的顶部,在类声明前添加两个USING语句,以包括驻留在命名空间和System.Text命名空间中的其他System.Messaging类。 (命名空间System.Text用于使用 StringBuilder 类,它是在连接 strings 时最好使用的新.NET Framework类。)

    using System.Messaging;
    using System.Text;
    
  14. 创建一个结构,其中包含用于保存定义付款的数据的变量。 若要创建 结构,请在 Main 过程后面添加以下代码:

    public struct Payment
    {
        public string Payor,Payee;
        public int Amount;
        public string DueDate;
    }
    
  15. 将以下步骤中的代码添加到 Clickbutton1事件。

    1. 将 结构的属性设置为窗体元素的值,如下所示:

      Payment myPayment;
      myPayment.Payor = textBox1.Text;
      myPayment.Payee = textBox2.Text;
      myPayment.Amount = Convert.ToInt32(textBox3.Text);
      myPayment.DueDate = textBox4.Text;
      
    2. 创建 类的 Message 实例,然后将 属性设置为 Body 结构 payment

      System.Messaging.Message msg = new System.Messaging.Message();
      msg.Body=myPayment;
      
    3. 若要将消息发送到 MSMQ,请创建 类的 MessageQueue 实例并调用 Send 传入 Message 对象的方法。 类 MessageQueue 是管理与 MSMQ 的交互的包装器。

      注意

      用于设置在计算机管理控制台中创建的专用队列路径的语法。 专用队列采用 的形式 machinename\Private$\queuename。 使用点或句点引用本地主机, (显示为 .) 。

      MessageQueue msgQ =new MessageQueue(".\\Private$\\billpay");
      msgQ.Send(msg);
      

      现在存在用于向 MSMQ 发送消息的代码。 .NET Framework使用 XMLMessageFormatter 对象自动序列化消息。 发送消息时隐式创建此对象。

  16. 将以下步骤中的代码添加到 Click button2 的事件。 事件处理程序 button2_Click 接收并处理事件处理程序中发送的 button1 付款消息。

    1. 第一行代码与第一个事件处理程序中的代码行相同:

      MessageQueue msgQ = new MessageQueue(".\\Private$\\billpay");
      
    2. 创建要传递给 XMLMessageFormatter 类的类型数组。

      注意

      接收消息时必须显式创建此类。 类的 XMLMessageFormatter 构造函数采用类型名称的字符串数组,或者更理想地采用 Type 类型数组:

      Payment myPayment=new Payment();
      Object o=new Object();
      System.Type[] arrTypes=new System.Type [2];
      arrTypes[0] = myPayment.GetType();
      arrTypes[1] = o.GetType();
      msgQ.Formatter = new XmlMessageFormatter(arrTypes);
      myPayment=((Payment)msgQ.Receive().Body);
      

      这些类型指示 XMLMessageFormatter 如何反序列化消息。

    3. 通过调用 Receive 方法接收消息。 Body访问 属性以读取消息内容。 属性 Body 返回对象,因此必须将 对象强制转换为付款类型才能以可用形式检索内容:

      StringBuilder sb = new StringBuilder();
      sb.Append("Payment paid to: " + myPayment.Payor);
      sb.Append("\n");
      sb.Append("Paid by: " + myPayment.Payee);
      sb.Append("\n");
      sb.Append("Amount: $" + myPayment.Amount.ToString());
      sb.Append("\n");
      sb.Append("Due Date: " + Convert.ToDateTime(myPayment.DueDate));
      
    4. 创建消息框以显示结果:

      MessageBox.Show(sb.ToString(), "Message Received!");
      

返回到顶部

完整的代码列表 (Form1.cs)

using System.Messaging;
using System.Text;
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

namespace WindowsApplication1
{
/// <summary>
/// Summary description for Form1.
/// </summary>
    public class Form1 : System.Windows.Forms.Form
    {
        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.Label label2;
        private System.Windows.Forms.Label label3;
        private System.Windows.Forms.Label label4;
        private System.Windows.Forms.TextBox textBox1;
        private System.Windows.Forms.TextBox textBox2;
        private System.Windows.Forms.TextBox textBox3;
        private System.Windows.Forms.TextBox textBox4;
        private System.Windows.Forms.Button button1;
        private System.Windows.Forms.Button button2;
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.Container components = null;
        public Form1()
        {
        // Required for Windows Form Designer support
            InitializeComponent();
        // TODO: Add any constructor code after InitializeComponent call
        }
        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        protected override void Dispose( bool disposing )
        {
            if( disposing )
            {
                if (components != null)
                {
                    components.Dispose();
                }
            }
            base.Dispose( disposing );
        }
        #region Windows Form Designer generated code
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.label1 = new System.Windows.Forms.Label();
            this.label2 = new System.Windows.Forms.Label();
            this.label3 = new System.Windows.Forms.Label();
            this.label4 = new System.Windows.Forms.Label();
            this.textBox1 = new System.Windows.Forms.TextBox();
            this.textBox2 = new System.Windows.Forms.TextBox();
            this.textBox3 = new System.Windows.Forms.TextBox();
            this.textBox4 = new System.Windows.Forms.TextBox();
            this.button1 = new System.Windows.Forms.Button();
            this.button2 = new System.Windows.Forms.Button();
            this.SuspendLayout();
            // label1
            this.label1.Location = new System.Drawing.Point(8, 24);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(104, 32);
            this.label1.TabIndex = 0;
            this.label1.Text = "Pay To:";
            // label2
            this.label2.Location = new System.Drawing.Point(8, 80);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(104, 32);
            this.label2.TabIndex = 1;
            this.label2.Text = "Your Name:";
            // label3
            this.label3.Location = new System.Drawing.Point(8, 136);
            this.label3.Name = "label3";
            this.label3.Size = new System.Drawing.Size(112, 32);
            this.label3.TabIndex = 2;
            this.label3.Text = "Amount:";
            // label4
            this.label4.Location = new System.Drawing.Point(8, 184);
            this.label4.Name = "label4";
            this.label4.Size = new System.Drawing.Size(104, 40);
            this.label4.TabIndex = 3;
            this.label4.Text = "Due To:";
            // textBox1
            this.textBox1.Location = new System.Drawing.Point(152, 24);
            this.textBox1.Name = "textBox1";
            this.textBox1.Size = new System.Drawing.Size(128, 20);
            this.textBox1.TabIndex = 4;
            this.textBox1.Text = "textBox1";
            // textBox2
            this.textBox2.Location = new System.Drawing.Point(160, 80);
            this.textBox2.Name = "textBox2";
            this.textBox2.TabIndex = 5;
            this.textBox2.Text = "textBox2";
            // textBox3
            this.textBox3.Location = new System.Drawing.Point(160, 128);
            this.textBox3.Name = "textBox3";
            this.textBox3.Size = new System.Drawing.Size(112, 20);
            this.textBox3.TabIndex = 6;
            this.textBox3.Text = "textBox3";
            // textBox4
            this.textBox4.Location = new System.Drawing.Point(160, 184);
            this.textBox4.Name = "textBox4";
            this.textBox4.Size = new System.Drawing.Size(120, 20);
            this.textBox4.TabIndex = 7;
            this.textBox4.Text = "textBox4";
            // button1
            this.button1.Location = new System.Drawing.Point(8, 232);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(104, 40);
            this.button1.TabIndex = 8;
            this.button1.Text = "Send Payment";
            this.button1.Click += new System.EventHandler(this.button1_Click);
            // button2
            this.button2.Location = new System.Drawing.Point(160, 232);
            this.button2.Name = "button2";
            this.button2.Size = new System.Drawing.Size(120, 40);
            this.button2.TabIndex = 9;
            this.button2.Text = "Process Payment";
            this.button2.Click += new System.EventHandler(this.button2_Click);
            // Form1
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
            this.ClientSize = new System.Drawing.Size(292, 273);
            this.Controls.Add(this.button2);
            this.Controls.Add(this.button1);
            this.Controls.Add(this.textBox4);
            this.Controls.Add(this.textBox3);
            this.Controls.Add(this.textBox2);
            this.Controls.Add(this.textBox1);
            this.Controls.Add(this.label4);
            this.Controls.Add(this.label3);
            this.Controls.Add(this.label2);
            this.Controls.Add(this.label1);
            this.Name = "Form1";
            this.Text = "Form1";
            this.ResumeLayout(false);
        }
        #endregion
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.Run(new Form1());
        }
        private void button1_Click(object sender, System.EventArgs e)
        {
            Payment myPayment;
            myPayment.Payor = textBox1.Text;
            myPayment.Payee = textBox2.Text;
            myPayment.Amount = Convert.ToInt32(textBox3.Text);
            myPayment.DueDate = textBox4.Text;
            System.Messaging.Message msg = new System.Messaging.Message();
            msg.Body=myPayment;
            MessageQueue msgQ =new MessageQueue(".\\Private$\\billpay");
            msgQ.Send(msg);
        }
        private void button2_Click(object sender, System.EventArgs e)
        {
            MessageQueue msgQ = new MessageQueue(".\\Private$\\billpay");
            Payment myPayment=new Payment();
            Object o=new Object();
            System.Type[] arrTypes=new System.Type [2];
            arrTypes[0] = myPayment.GetType();
            arrTypes[1] = o.GetType();
            msgQ.Formatter = new XmlMessageFormatter(arrTypes);
            myPayment=((Payment)msgQ.Receive().Body);
            StringBuilder sb = new StringBuilder();
            sb.Append("Payment paid to: " + myPayment.Payor);
            sb.Append("\n");
            sb.Append("Paid by: " + myPayment.Payee);
            sb.Append("\n");
            sb.Append("Amount: $" + myPayment.Amount.ToString());
            sb.Append("\n");
            sb.Append("Due Date: " + Convert.ToDateTime(myPayment.DueDate));
            MessageBox.Show(sb.ToString(), "Message Received!");
        }
        public struct Payment
        {
            public string Payor,Payee;
            public int Amount;
            public string DueDate;
        }
    }
}

注意

应在 Visual Studio 2005 中更改代码。 创建Windows 窗体项目时,默认情况下,Visual C# 会向项目添加一个窗体。 此窗体名为 Form1。 表示窗体的两个文件名为 Form1.csForm1.designer.cs。 使用 Form1.cs 编写代码。 Designer.cs 文件是Windows 窗体 Designer写入实现通过添加控件执行的所有操作的代码的位置。 有关 Visual C# 2005 中Windows 窗体 Designer的详细信息,请参阅创建 Visual C# (项目 )

返回到顶部

验证代码

  1. “调试” 菜单上,单击“ 启动”。

  2. 在每个文本框中键入值,然后单击“ 发送付款”。

  3. 返回到计算机管理控制台。 单击 billpay 下的“专用队列”中的“队列邮件”文件夹,然后验证 MSMQ 是否收到了 (信封图标) 指示的消息。

  4. 右键单击邮件,单击“ 属性”,然后单击“ 正文 ”选项卡。你会注意到付款消息。

    注意

    付款消息的内容序列化为 XML。

  5. 返回到帐单支付 Windows 应用程序,然后单击“ 处理付款 ”按钮。 你将看到一个消息框,用于确认邮件的接收并显示该消息。

返回到顶部

疑难解答

  • 缺少专用队列通常仅在 Windows 2000 专业版和 Windows XP 专业版上是一个问题。 Windows 2000 Server 和 Windows XP Server 允许使用公共队列。

  • 将正确的参数传递给 XMLMessageFormatter() 可能比较棘手。 在此示例中,如果对象或付款类型未包含在传递给构造函数的 Type 数组中,则会引发异常。

返回到顶部