消息队列

 

  在这个数组内部,CWorker 类创建了 CWorkerThread类的一个实现版
本。CWorkerThread 类(将在下面讨论)是一个必须继承的抽象类。导出
类定义了消息的处理方式:
aThreads = new ArrayList();
for (int idx=0; idx〈sfWorker.NumberThreads; idx++)
{
  WorkerThreadFormatter wfThread = new WorkerThreadFormatter();
  wfThread.ProcessName = sfWorker.ProcessName;
  wfThread.ProcessDesc = sfWorker.ProcessDesc;
  wfThread.ThreadNumber = idx;
  wfThread.InputQueue = sfWorker.InputQueue;
  wfThread.ErrorQueue = sfWorker.ErrorQueue;
  wfThread.OutputName = sfWorker.OutputName;
  // 定义辅助类型,并将其插入辅助线程结构
  CWorkerThread wtBase;
  switch (sfWorker.ProcessType)
  {
   case WorkerFormatter.SFProcessType.ProcessRoundRobin:
     wtBase = new CWorkerThreadRoundRobin(this, wfThread);
     break;
   case WorkerFormatter.SFProcessType.ProcessAppSpecific:
     wtBase = new CWorkerThreadAppSpecific(this, wfThread);
     break;
   case WorkerFormatter.SFProcessType.ProcessAssembly:
     wtBase = new CWorkerThreadAssembly(this, wfThread);
     break;
   default:
     throw new Exception("Unknown Processing Type");
  }
  // 添加对数组的调用
  aThreads.Insert(idx, wtBase);
}

  一旦所有的对象都已创建,就可以通过调用每个线程对象的 Start方
法来启动它们:
foreach(CWorkerThread cThread in aThreads)
  cThread.Start();

  Stop、Pause 和 Continue 方法在 foreach循环里执行的操作类似。
Stop方法具有如下的垃圾收集操作:
GC.SuppressFinalize(this);

  在类析构函数中将调用 Stop 方法,这样,在没有显式调用 Stop 方
法的情况下也可以正确地终止对象。如果调用了 Stop 方法,将不需要析
构函数。SuppressFinalize方法能够防止调用对象的 Finalize 方法(析
构函数的实际实现)。

CWorkerThread 抽象类

  CWorkerThread 是一个由 CWorkerThreadAppSpecifc、CWorkerThread
RoundRobin 和 CWorkerThreadAssembly继承的抽象类。无论如何处理消
息,队列的大部分处理是相同的,所以 CWorkerThread类提供了这一功能。
这个类提供了抽象方法(必须被实际方法替代)以管理资源和处理消息。

  类的工作再一次通过 Start、Stop、Pause 和 Continue 方法来实现。
在 Start方法中引用了输入和错误队列。在 .NET 框架中,消息由 System.
Messaging 名称空间处理:
// 尝试打开队列,并设置默认的读写属性
MessageQueue mqInput = new MessageQueue(sInputQueue);
mqInput.MessageReadPropertyFilter.Body = true;
mqInput.MessageReadPropertyFilter.AppSpecific = true;
MessageQueue mqError = new MessageQueue(sErrorQueue);
// 如果使用 MSMQ COM,则将格式化程序设置为 ActiveX
mqInput.Formatter = new ActiveXMessageFormatter();
mqError.Formatter = new ActiveXMessageFormatter();

 

  一旦定义了消息队列引用,即会创建一个线程用于实际的处理函数
(称为 ProcessMessages)。在 .NET 框架中,使用 System.Threading
名称空间很容易实现线程处理:
procMessage = new Thread(new ThreadStart(ProcessMessages));
procMessage.Start();

  ProcessMessages 函数是基于 Boolean值的处理循环。当数值设为
False,处理循环将终止。因此,线程对象的 Stop 方法只设置这一Boolean
值,然后关闭打开的消息队列,并加入带有主线程的线程:
// 加入服务线程和处理线程
bRun = false;
procMessage.Join();
// 关闭打开的消息队列
mqInput.Close();
mqError.Close();

Pause 方法只设置一个 Boolean 值,使处理线程休眠半秒钟:

if (bPause)
  Thread.Sleep(500);

  最后,每一个 Start、Stop、Pause 和 Continue 方法将调用抽象的
OnStart 、OnStop、OnPause 和 OnContinue 方法。这些抽象方法为实现
的类提供了挂钩,以捕获和释放所需的资源。

  ProcessMessages 循环具有如下基本结构:
●接收Message。
●如果Message具有成功的Receive,则调用抽象ProcessMessage方法。
●如果Receive或ProcessMessage失败,将Message发送至错误队列中。

Message mInput;
try
{
  // 从队列中读取,并等候 1 秒
  mInput = mqInput.Receive(new TimeSpan(0,0,0,1));
}
catch (MessageQueueException mqe)
{
  // 将消息设置为 null
  mInput = null;
  // 查看错误代码,了解是否超时
  if (mqe.ErrorCode != (-1072824293) ) //0xC00E001B
  {
   // 如果未超时,发出一个错误并记录错误号
   LogError("Error: " + mqe.Message);
   throw mqe;
  }
}
if (mInput != null)
{
  // 得到一个要处理的消息,调用处理消息抽象方法
  try
  {
   ProcessMessage(mInput);
  }
  // 捕获已知异常状态的错误
  catch (CWorkerThreadException ex)
  {
   ProcessError(mInput, ex.Terminate);
  }
  // 捕获未知异常,并调用 Terminate
  catch
  {
   ProcessError(mInput, true);
  }
}

 

  ProcessError方法将错误的消息发送至错误队列。另外,它也可能引
发异常来终止线程。如果ProcessMessage方法引发了终止错误或 CWorker
ThreadException类型,它将执行此操作。

CworkerThread 导出类

  任何从 CWorkerThread中继承的类都必须提供 OnStart、OnStop、On
Pause、OnContinue和 ProcessMessage 方法。OnStart 和 OnStop方法获
取并释放处理资源。OnPause 和 OnContinue 方法允许临时释放和重新获
取这些资源。ProcessMessage方法应该处理消息,并在出现失败事件时引
发 CWorkerThreadException 异常。

  由于 CWorkerThread构造函数定义运行时参数,导出类必须调用基类
构造函数:
public CWorkerThreadDerived(CWorker v_cParent, WorkerThread
Formatter v_wfThread)
  : base (v_cParent, v_wfThread) {}

  导出类提供了两种类型的处理:将消息发送至另一队列,或者调用组
件方法。接收和发送消息的两种实现使用了循环技术或应用程序偏移(保
留在消息 AppSpecific属性中),作为使用哪一队列的决定因素。此方案
中的配置文件应该包括队列路径的列表。实现的 OnStart和 OnStop 方法
应该打开和关闭对这些队列的引用:
iQueues = wfThread.OutputName.Length;
mqOutput = new MessageQueue[iQueues];
for (int idx=0; idx〈iQueues; idx++)
{
  mqOutput[idx] = new MessageQueue(wfThread.OutputName[idx]);
  mqOutput[idx].Formatter = new ActiveXMessageFormatter();
}

  在这些方案中,消息的处理很简单:将消息发送必要的输出队列。在
循环情况下,这个进程为:
try
{
  mqOutput[iNextQueue].Send(v_mInput);
}
catch (Exception ex)
{
  // 如果错误强制终止异常
  throw new CWorkerThreadException(ex.Message, true);
}
// 计算下一个队列号
iNextQueue++;
iNextQueue %= iQueues;

  后一种调用带消息参数的组件的实现方法比较有趣。ProcessMessage
方法使用 IWebMessage接口调入一个 .NET 组件。OnStart 和 OnStop 方
法获取和释放此组件的引用。

  此方案中的配置文件应该包含两个项目:完整的类名和类所在文件的
位置。按照 IWebMessage接口中的定义,在组件上调用 Process方法。

  要获取对象引用,需要使用 Activator.CreateInstance 方法。此函
数需要一个程序集类型。在这里,它是从程序集文件路径和类名中导出的。
一旦获取对象引用,它将被放入合适的接口:
private IWebMessage iwmSample;
private string sFilePath, sTypeName;
// 保存程序集路径和类型名称
sFilePath = wfThread.OutputName[0];
sTypeName = wfThread.OutputName[1];
// 获取对必要对象的引用
Assembly asmSample = Assembly.LoadFrom(sFilePath);
Type

typSample = asmSample.GetType(sTypeName);
object objSample = Activator.CreateInstance(typSample);
// 定义给对象的必要接口
iwmSample = (IWebMessage)objSample;

 

  获取对象引用后,ProcessMessage方法将在 IWebMessage接口上调用
Process 方法:
WebMessageReturn wbrSample;
try
{
  // 定义方法调用的参数
  string sLabel = v_mInput.Label;
  string sBody = (string)v_mInput.Body;
  int iAppSpecific = v_mInput.AppSpecific;
  // 调用方法并捕捉返回代码
  wbrSample = iwmSample.Process(sLabel, sBody, iAppSpecific);
}
catch (InvalidCastException ex)
{
  // 如果在消息内容中发生错误,则强制发出一个非终止异常
  throw new CWorkerThreadException(ex.Message, false);
}
catch (Exception ex)
{
  // 如果错误调用程序集,则强制发出终止异常
  throw new CWorkerThreadException(ex.Message, true);
}
// 如果没有错误,则检查对象调用的返回状态
switch (wbrSample)
{
  case WebMessageReturn.ReturnBad:
   throw new CWorkerThreadException
     ("Unable to process message: Message marked bad", false);
  case WebMessageReturn.ReturnAbort:
   throw new CWorkerThreadException
     ("Unable to process message: Process terminating", true);
  default:
   break;
}

  提供的示例组件将消息正文写入数据库表。如果捕获到严重数据库错
误,您可能希望终止处理过程,但是在这里,仅仅将消息标记为错误的消
息。

  由于此示例中创建的类实例可能会获取并保留昂贵的数据库资源,所
以用 OnPause和 OnContinue 方法释放和重新获取对象引用。

检测设备

  就象在所有优秀的应用程序中一样,检测设备用于监测应用程序的状
态。。NET 框架大大简化了将事件日志、性能计数器和 Windows管理检测
设备(WMI )纳入应用程序的过程。消息应用程序使用时间日志和性能计
数器,二者都是来自 System.Diagnostics 程序集。

  在 ServiceBase类中,您可以自动启用事件日志。另外,ServiceBase
EventLog成员支持写入应用程序事件日志:
EventLog.WriteEntry(sMyMessage, EventLogEntryType.Information);

  对于写入事件日志而不是应用程序日志的应用程序,它能够很容易地
创建和获取 EventLog 资源的引用(正如在 CWorker类中所做的一样),
并能够使用 WriteEntry 方法记录日志项:
private EventLog cLog;
string sSource = ServiceControl.ServiceControlName;
string sLog = "Application";
// 查看源是否存在,如果不存在,则创建源
if (!EventLog.SourceExists(sSource))
  EventLog.Creat

eEventSource(sSource, sLog);
// 创建日志对象,并引用现在定义的源
cLog = new EventLog();
cLog.Source = sSource;
// 在日志中写入条目,表明创建成功
cLog.WriteEntry("已成功创建", EventLogEntryType.Information);

 

  .NET 框架大大简化了性能计数器。对于每一个处理线程、线程导出
的用户和整个应用程序,这一消息应用程序都能提供计数器,用于跟踪消
息数量和每秒钟处理消息的数量。要提供此功能,您需要定义性能计数器
的类别,然后增加相应的计数器实例。

  性能计数器的类别在服务 OnStart方法中定义。这些类别代表两种计
数器——消息总数和每秒钟处理的消息数:
CounterCreationData[] cdMessage = new CounterCreationData[2];
cdMessage[0] = new CounterCreationData("Messages/Total", "Total
Messages Processed",
PerformanceCounterType.NumberOfItems64);
cdMessage[1] = new CounterCreationData("Messages/Second",
"Messages Processed a Second",
PerformanceCounterType.RateOfChangePerSecond32);
PerformanceCounterCategory.Create("MSDN Message Service", "MSDN
Message Service Counters", cdMessage);

  一旦定义了性能计数器类别,将创建 PerformanceCounter 对象以访
问计数器实例功能。PerformanceCounter对象需要类别、计数器名称和一
个可选的实例名称。对于辅助进程,将使用来自 XML文件的进程名称,代
码如下:
pcMsgTotWorker = new PerformanceCounter("MSDN Message Service",
"Messages/Total", sProcessName);
pcMsgSecWorker = new PerformanceCounter("MSDN Message Service",
"Messages/Second", sProcessName);
pcMsgTotWorker.RawValue = 0;
pcMsgSecWorker.RawValue = 0;

要增加计数器的值,仅仅需要调用适当的方法:

pcMsgTotWorker.IncrementBy(1);
pcMsgSecWorker.IncrementBy(1);

最后说明一点,服务终止时,安装的性能计数器类别应该从系统中删除:

PerformanceCounterCategory.Delete("MSDN Message Service");

  由于性能计数器在 .NET 框架中工作,因此需要运行一项特殊的服务。
此服务(PerfCounterService)提供了共享内存。计数器信息将写入共享
内存,并被性能计数器系统读取。

安装

  在结束以前,我们来简要介绍一下安装以及称为 installutil.exe的
安装工具。由于此应用程序是 Windows服务,它必须使用installutil.exe
来安装。因此,需要使用一个从 System.Configuration.Install 程序集
中继承的 Installer类:
public class ServiceRegister: Installer
{
  private ServiceInstaller serviceInstaller;
  private ServiceProcessInstaller processInstaller;
  public ServiceRegi

ster()
  {
   // 创建服务安装程序
   serviceInstaller = new ServiceInstaller();
   serviceInstaller.StartType = ServiceStart.Manual;
   serviceInstaller.ServiceName = ServiceControl.ServiceControl
   Name;
   serviceInstaller.DisplayName = ServiceControl.ServiceControl
   Desc;
   Installers.Add(serviceInstaller);
   // 创建进程安装程序
   processInstaller = new ServiceProcessInstaller();
   processInstaller.RunUnderSystemAccount = true;
   Installers.Add(processInstaller);
  }
}

 

  如此示例类所示,对于一个 Windows服务,服务和服务进程各需要一
个安装程序,以定义运行服务的帐户。其他安装程序允许注册事件日志和
性能计数器等资源。

总结

  从这个 .NET 框架应用程序示例中可以看出,以前只有 Visual C++
程序员能够编写的应用程序,现在使用简单的面向对象程序即可实现。尽
管我们的重点是 C# ,但本文所述的内容也同样适用于 Visual Basic 和
Managed C++.新的 .NET 框架使开发人员能够使用任何编程语言来创建功
能强大、可伸缩的 Windows应用程序和服务。

  新的 .NET 框架不仅简化和扩展了编程的种种可能,还能够轻松地将
人们经常遗忘的应用程序检测设备(例如性能监测计数器和事件日志通知)
合并到应用程序中。尽管这里的应用程序没有使用 Windows管理检测设备
(WMI ),但 .NET 框架同样也可以应用它。

 

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

namespace WinMsmq
{
 /// <summary>
 /// Form1 的摘要说明。
 /// </summary>
 public class Form1 : System.Windows.Forms.Form
 {
  static ManualResetEvent signal = new ManualResetEvent(false);
  static ManualResetEvent  pubRecvieSignal=new ManualResetEvent(false);
  private System.Messaging.MessageQueue mq=null;
  private readonly  string  qryname=@"";
  private  MessageQueue msq=null;
  private  MessageQueue pubMsq=null;
  private System.Windows.Forms.Button button1;
  private System.Windows.Forms.Button button2;
  private System.Windows.Forms.Button button3;
  private System.Windows.Forms.RichTextBox richTextBox1;
  private System.Windows.Forms.GrouPBox groupBox1;
  private System.Windows.Forms.GroupBox groupBox2;
  private System.Windows.Forms.Button button5;
  private System.Windows.Forms.Button button6;
  private System.Windows.Forms.Button button7;
  private System.Windows.Forms.GroupBox groupBox3;
  private System.Windows.Forms.Button sendToPub;
  private System.Windows.Forms.Button readFromPub;
  private System.Windows.Forms.Button Creaet;
  private System.Windows.Forms.Button button4;
  private System.Windows.Forms.Button delPubmsg;
  private System.Windows.Forms.Button srPub;
  private System.Data.SqlClient.SqlConnection sqlConnection1;
  /// <summary>
  /// 必需的设计器变量。
  /// </summary>
  private System.ComponentModel.Container components = null;
  public Form1()
  {
   //
   // Windows 窗体设计器支持所必需的
   //
   InitializeComponent();
   this.qryname=System.Configuration.ConfigurationSettings.AppSettings["pubMsmqQryName"];
   if(MessageQueue.Exists(qryname))
   {
    this.pubMsq=new MessageQueue(qryname,true);
   }
   else
   {
    this.pubMsq=System.Messaging.MessageQueue.Create(qryname,true);
   }
   this.richTextBox1.AppendText("==================\r\n");
   this.richTextBox1.AppendText(this.pubMsq .QueueName +":公共队列创建成功!\r\n");

   //
   // TODO: 在 InitializeComponent 调用后添加任何构造函数代码
   //
  }
  /// <summary>
  /// 清理所有正在使用的资源
  /// </summary>
  protected override void Dispose( bool disposing )
  {
   if( disposing )
   {
    if (components != null)
    {
     components.Dispose();
    }
   }
   base.Dispose( disposing );
  }

  #region Windows 窗体设计器生成的代码
  /// <summary>
  /// 设计器支持所需的方法 - 不要使用代码编辑器修改
  /// 此方法的内容。
  /// </summary>
  private void InitializeComponent()
  {
   this.button1 = new System.Windows.Forms.Button();
   this.button2 = new System.Windows.Forms.Button();
   this.button3 = new System.Windows.Forms.Button();
   this.richTextBox1 = new System.Windows.Forms.RichTextBox();
   this.groupBox1 = new System.Windows.Forms.GroupBox();
   this.groupBox2 = new System.Windows.Forms.GroupBox();
   this.button4 = new System.Windows.Forms.Button();
   this.button7 = new System.Windows.Forms.Button();
   this.Creaet = new System.Windows.Forms.Button();
   this.button6 = new System.Windows.Forms.Button();
   this.button5 = new System.Windows.Forms.Button();
   this.groupBox3 = new System.Windows.Forms.GroupBox();
   this.srPub = new System.Windows.Forms.Button();
   this.delPubmsg = new System.Windows.Forms.Button();
   this.readFromPub = new System.Windows.Forms.Button();
   this.sendToPub = new System.Windows.Forms.Button();
   this.sqlConnection1 = new System.Data.SqlClient.SqlConnection();
   this.groupBox1.SuspendLayout();
   this.groupBox2.SuspendLayout();
   this.groupBox3.SuspendLayout();
   this.SuspendLayout();
   //
   // button1
   //
   this.button1.Location = new System.Drawing.Point(8, 56);
   this.button1.Name = "button1";
   this.button1.TabIndex = 0;
   this.button1.Text = "SendMsg";
   this.button1.Click += new System.EventHandler(this.button1_Click);
   //
   // button2
   //
   this.button2.Location = new System.Drawing.Point(8, 16);
   this.button2.Name = "button2";
   this.button2.TabIndex = 1;
   this.button2.Text = "CreateMsmq";
   this.button2.Click += new System.EventHandler(this.button2_Click);
   //
   // button3
   //
   this.button3.Location = new System.Drawing.Point(8, 104);
   this.button3.Name = "button3";
   this.button3.TabIndex = 2;
   this.button3.Text = "ReadMsg";
   this.button3.Click += new System.EventHandler(this.button3_Click);
   //
   // richTextBox1
   //
   this.richTextBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
    | System.Windows.Forms.AnchorStyles.Left)
    | System.Windows.Forms.AnchorStyles.Right)));
   this.richTextBox1.Location = new System.Drawing.Point(0, 152);
   this.richTextBox1.Name = "richTextBox1";
   this.richTextBox1.Size = new System.Drawing.Size(640, 188);
   this.richTextBox1.TabIndex = 3;
   this.richTextBox1.Text = "richTextBox1";
   //
   // groupBox1
   //
   this.groupBox1.Controls.Add(this.button2);
   this.groupBox1.Controls.Add(this.button1);
   this.groupBox1.Controls.Add(this.button3);
   this.groupBox1.Location = new System.Drawing.Point(16, 0);
   this.groupBox1.Name = "groupBox1";
   this.groupBox1.Size = new System.Drawing.Size(144, 136);
   this.groupBox1.TabIndex = 4;
   this.groupBox1.TabStop = false;
   this.groupBox1.Text = "非事务";
   //
   // groupBox2
   //
   this.groupBox2.Controls.Add(this.button4);
   this.groupBox2.Controls.Add(this.button7);
   this.groupBox2.Controls.Add(this.Creaet);
   this.groupBox2.Controls.Add(this.button6);
   this.groupBox2.Controls.Add(this.button5);
   this.groupBox2.Location = new System.Drawing.Point(184, 0);
   this.groupBox2.Name = "groupBox2";
   this.groupBox2.Size = new System.Drawing.Size(240, 136);
   this.groupBox2.TabIndex = 5;
   this.groupBox2.TabStop = false;
   this.groupBox2.Text = "事务性";
   //
   // button4
   //
   this.button4.Location = new System.Drawing.Point(168, 80);
   this.button4.Name = "button4";
   this.button4.Size = new System.Drawing.Size(56, 48);
   this.button4.TabIndex = 5;
   this.button4.Text = "CreateMsmqWithTran";
   this.button4.Click += new System.EventHandler(this.button4_Click);
   //
   // button7
   //
   this.button7.Location = new System.Drawing.Point(16, 104);
   this.button7.Name = "button7";
   this.button7.Size = new System.Drawing.Size(136, 23);
   this.button7.TabIndex = 4;
   this.button7.Text = "ClearMsgOfRichTxtBox";
   this.button7.Click += new System.EventHandler(this.button7_Click);
   //
   // Creaet
   //
   this.Creaet.Location = new System.Drawing.Point(144, 32);
   this.Creaet.Name = "Creaet";
   this.Creaet.Size = new System.Drawing.Size(80, 40);
   this.Creaet.TabIndex = 3;
   this.Creaet.Text = "异步读取消息";
   this.Creaet.Click += new System.EventHandler(this.Read);
   //
   // button6
   //
   this.button6.Location = new System.Drawing.Point(16, 72);
   this.button6.Name = "button6";
   this.button6.Size = new System.Drawing.Size(104, 23);
   this.button6.TabIndex = 2;
   this.button6.Text = "ReadMsgTran";
   this.button6.Click += new System.EventHandler(this.button6_Click);
   //
   // button5
   //
   this.button5.Location = new System.Drawing.Point(16, 32);
   this.button5.Name = "button5";
   this.button5.Size = new System.Drawing.Size(104, 24);
   this.button5.TabIndex = 1;
   this.button5.Text = "SendMsgTran";
   this.button5.Click += new System.EventHandler(this.button5_Click);
   //
   // groupBox3
   //
   this.groupBox3.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
    | System.Windows.Forms.AnchorStyles.Right)));
   this.groupBox3.Controls.Add(this.srPub);
   this.groupBox3.Controls.Add(this.delPubmsg);
   this.groupBox3.Controls.Add(this.readFromPub);
   this.groupBox3.Controls.Add(this.sendToPub);
   this.groupBox3.Location = new System.Drawing.Point(432, 0);
   this.groupBox3.Name = "groupBox3";
   this.groupBox3.Size = new System.Drawing.Size(208, 136);
   this.groupBox3.TabIndex = 6;
   this.groupBox3.TabStop = false;
   this.groupBox3.Text = "公共队列";
   //
   // srPub
   //
   this.srPub.Location = new System.Drawing.Point(144, 72);
   this.srPub.Name = "srPub";
   this.srPub.Size = new System.Drawing.Size(56, 48);
   this.srPub.TabIndex = 4;
   this.srPub.Text = "检索公共队列";
   this.srPub.Click += new System.EventHandler(this.srPub_Click);
   //
   // delPubmsg
   //
   this.delPubmsg.Location = new System.Drawing.Point(8, 96);
   this.delPubmsg.Name = "delPubmsg";
   this.delPubmsg.Size = new System.Drawing.Size(112, 24);
   this.delPubmsg.TabIndex = 3;
   this.delPubmsg.Text = "DeletePubMsmg";
   this.delPubmsg.Click += new System.EventHandler(this.delPubmsg_Click);
   //
   // readFromPub
   //
   this.readFromPub.Location = new System.Drawing.Point(8, 64);
   this.readFromPub.Name = "readFromPub";
   this.readFromPub.Size = new System.Drawing.Size(128, 24);
   this.readFromPub.TabIndex = 2;
   this.readFromPub.Text = "ReadMsgFromPubMsmg";
   this.readFromPub.Click += new System.EventHandler(this.readFromPub_Click);
   //
   // sendToPub
   //
   this.sendToPub.Location = new System.Drawing.Point(8, 32);
   this.sendToPub.Name = "sendToPub";
   this.sendToPub.Size = new System.Drawing.Size(144, 24);
   this.sendToPub.TabIndex = 1;
   this.sendToPub.Text = "SendMsgToPubMsmq";
   this.sendToPub.Click += new System.EventHandler(this.sendToPub_Click);
   //
   // sqlConnection1
   //
   this.sqlConnection1.ConnectionString = "workstation id=DHZ;packet size=4096;integrated security=SSPI;data source=\"DHZ\\DHZ" +
    "\";persist security info=False;initial catalog=Northwind";
   //
   // Form1
   //
   this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
   this.ClientSize = new System.Drawing.Size(648, 349);
   this.Controls.Add(this.groupBox3);
   this.Controls.Add(this.groupBox2);
   this.Controls.Add(this.groupBox1);
   this.Controls.Add(this.richTextBox1);
   this.Name = "Form1";
   this.Text = "Form1";
   this.Load += new System.EventHandler(this.Form1_Load);
   this.groupBox1.ResumeLayout(false);
   this.groupBox2.ResumeLayout(false);
   this.groupBox3.ResumeLayout(false);
   this.ResumeLayout(false);

  }
  #endregion

  /// <summary>
  /// 应用程序的主入口点。
  /// </summary>
  [STAThread]
  static void Main()
  {
   Application.Run(new Form1());
  }
  private void Form1_Load(object sender, System.EventArgs e)
  {
   
   if(MessageQueue.Exists(@".\private$\dhzOrderMgmt"))
   {
    this.mq=new MessageQueue(@".\private$\dhzOrderMgmt");
   }
   else
   {
    this.mq=MessageQueue.Create(@".\private$\dhzOrderMgmt",false);
   }
   this.richTextBox1.AppendText("==================\r\n");
   this.richTextBox1.AppendText(mq.QueueName +":创建成功!\r\n");
  
  
  }
  private void button1_Click(object sender, System.EventArgs e)
  {
   Od od=new Od("代汉章","南昌",DateTime.Now.ToLongTimeString ());
   if(this.mq.Transactional)
   {
    this.mq.Send(od,new System.Messaging.MessageQueueTransaction ());
   }
   else
   {
    this.mq.Send(od);
   }
   this.richTextBox1.AppendText("发送成功!\r\n");
  }
  private void button2_Click(object sender, System.EventArgs e)
  {
  
   if(MessageQueue.Exists(@".\private$\dhzOrderMgmt"))
   {
    this.mq=new MessageQueue(@".\private$\dhzOrderMgmt");
   }
   else
   {
    this.mq=MessageQueue.Create(@".\private$\dhzOrderMgmt",false);
   }
   this.richTextBox1.AppendText("==================\r\n");
   this.richTextBox1.AppendText(mq.QueueName +":创建成功!\r\n");
  

  }
  private void button3_Click(object sender, System.EventArgs e)
  {
   if(this.mq!=null)
   {
    System.Messaging.MessageEnumerator  msg=this.mq.GetMessageEnumerator ();
    while(msg.MoveNext ())
    {
     System.Messaging .Message oc=msg.Current ;
     Od od=oc.Body  as Od ;
     this.richTextBox1.AppendText(od.Name +":"+od.City +":"+od.Time +";\r\n");
    
    }

   }
  }
  private void button4_Click(object sender, System.EventArgs e)
  {
   if(MessageQueue.Exists(@".\private$\dhzTrans"))
   {
    this.msq =new MessageQueue(@".\private$\dhzTrans");
   }
   else
   {
    this.msq=MessageQueue.Create(@".\private$\dhzTrans",true);
   }
   this.richTextBox1.AppendText("==================\r\n");
   this.richTextBox1.AppendText(msq.QueueName +":创建成功!\r\n");
  
  }
  private void button5_Click(object sender, System.EventArgs e)
  {
   
   this.msq=new MessageQueue(@".\private$\dhzTrans");
   if(this.msq.Transactional)
   {
    Od od=new Od("万卿","景德镇",DateTime.Now.ToString("u"));
    MessageQueueTransaction myTransaction = new
                MessageQueueTransaction();
          myTransaction.Begin();
       msq.Send(od,myTransaction);
                myTransaction.Commit();
    this.richTextBox1.AppendText("OK!发送成功:"+od.Time+"\r\n" );
   }

  }
  private void button6_Click(object sender, System.EventArgs e)
  {
   this.msq=new MessageQueue(@".\private$\dhzTrans");
   if(this.msq .Transactional )
   {
    MessageQueueTransaction myTransaction = new MessageQueueTransaction();
    this.msq.Formatter=new System.Messaging.XMLMessageFormatter (new Type[]{Type.GetType("WinMsmq.Od" )});
    myTransaction.Begin();
    System.Messaging.Message ms=msq.Receive(myTransaction);
    Od od=ms.Body as Od ;
    this.richTextBox1.AppendText(od.Name +":"+od.City +":"+od.Time +";\r\n");
    myTransaction.Commit();
    this.richTextBox1.AppendText("OK!发送成功\r\n");
   }
  }
  private void Read(object sender, System.EventArgs e)
  {
   this.msq=new MessageQueue(@".\private$\dhzTrans");
   if(this.msq.Transactional)
   {
    MessageQueueTransaction myTransaction = new MessageQueueTransaction();
    msq.ReceiveCompleted += new ReceiveCompletedEventHandler(MyReceiveCompleted);
    this.msq.Formatter=new System.Messaging.XmlMessageFormatter (new Type[]{Type.GetType("WinMsmq.Od" )});
    myTransaction.Begin();
                msq.BeginReceive();
    Form1.signal.WaitOne ();
    myTransaction.Commit ();
   }
  }
  private  void MyReceiveCompleted(Object source,ReceiveCompletedEventArgs asyncResult)
  {
   try
   {
    MessageQueue mq = (MessageQueue)source;
    System.Messaging .Message m = mq.EndReceive(asyncResult.AsyncResult);
    Form1.signal.Set ();
                Od od=m.Body as Od ;
     this.richTextBox1.AppendText ("Read:"+od.Name +":"+od.City +":"+od.Time +"\r\n"+"插入数据库完成\r\n");
    mq.BeginReceive();
   }
   catch(MessageQueueException c)
   {
         this.richTextBox1.AppendText("Error:"+c.Message +"\r\n");
    this.button5.Enabled=false;
   }
            // Handle other exceptions.
           
   
  }
  private void button7_Click(object sender, System.EventArgs e)
  {
   this.richTextBox1.Clear ();
  }
  private void delPubmsg_Click(object sender, System.EventArgs e)
  {
   //删除创建的公共队列
   System.Messaging.MessageQueue.Delete (qryname);
  }
  private void srPub_Click(object sender, System.EventArgs e)
  {
      MessageQueue[]  mq=System.Messaging.MessageQueue.GetPublicQueuesByMachine ("dhz");
   for(int i=0;i<mq.Length ;i++)
   {
    this.richTextBox1.AppendText(mq[i].QueueName +":\r\n");
   }

  }
  private void sendToPub_Click(object sender, System.EventArgs e)
  {
      if(this.pubMsq==null)
      this.pubMsq=new MessageQueue(this.qryname );
   if(this.pubMsq.Transactional  )
   {
    Od od=new Od("万卿","景德镇",DateTime.Now.ToString("u"));
    MessageQueueTransaction myTransaction = new
     MessageQueueTransaction();
    myTransaction.Begin();
    pubMsq.Send(od,myTransaction);
    myTransaction.Commit();
   }
  }
  private void readFromPub_Click(object sender, System.EventArgs e)
  {
   this.pubMsq=new MessageQueue(this.qryname );
   if(this.pubMsq.Transactional)
   {
    MessageQueueTransaction myTransaction = new MessageQueueTransaction();
    pubMsq.ReceiveCompleted += new ReceiveCompletedEventHandler(MyReceiveCompleted);
    this.pubMsq.Formatter=new System.Messaging.XmlMessageFormatter (new Type[]{Type.GetType("WinMsmq.Od" )});
    myTransaction.Begin();
    pubMsq.BeginReceive();
    Form1.signal.WaitOne ();
    myTransaction.Commit ();
   }
  
  }

  

 }
}
/////////////////////////================
public class Od
 {
  public Od()
  {
   //
   // TODO: 在此处添加构造函数逻辑
   //
  }
  public Od(string  na,string cty,string timestr)
  {
   this.name=na;
   this.city=cty;
   this.time=timestr;

  }
  private string  time="";
  private string name;
  private string city;
  public string Name
  {
   get{return this.name ;}
   set{this.name=value;}
  }
  public string City
  {
   get{return this.city ;}
   set{this.city=value;}
  }
  public string Time
  {
   get{return this.time ;}
   set{this.time=value;}
  }
 }
=======================App.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
  <!--ComputerName-->
  <!--dhz:是域控制器所在的计算机名:-->
     <add key="QcName" value="dhz\FormatName:Public=620B1BFB-18E9-4d80-B869-FF6FB2DFDD08"></add>
  </appSettings>
</configuration>


posted on 2007-04-28 09:54  曾伟  阅读(348)  评论(0编辑  收藏  举报

导航