在.NET中使用COM+队列组件

转载 2007年09月25日 10:12:00

.NET在异步函数调用上作了很大的努力。通过“代表(DELEGATE)”程序员可以非常方便对函数进行异步调用。编译器在幕后加入了BeginEnvoke()以及EndEnvoke()函数的定义和实体,这样你可以对对象的函数进行异步调用,并方便地拿到函数返回结果。

但是.NET提供的异步调用还不能完全取代COM+队列组件提供的异步功能,原因如下:

第一,.NET不支持断开的网络。客户端和服务器程序必须同时在线运行,并且中间的网络必须保持连接;

第二,在.NET中为使用异步调用,客户端程序要做不少改动。使用的方法和通常的同步调用有不小的区别;

第三,.NET没有不支持“自动再试(Auto-Retry")”机制。总之,如果你涉及到异步调用,COM+提供的队列组件应该是一个值得考虑的方案。

 

COM+队列组件的工作原理

COM+的队列组件是COM+和Microsoft提供的消息队列服务(MSMQ)相结合的产物。本质上讲是利用了“消息中间层”来将客户端和服务器端程序异步地连接在一起。MSMQ提供了消息的中间存储和传递服务。

从表面上看,客户端程序创建了队列组件类的实例,并调用实例的函数。但实际上,这只是一个假象。你创建的只是一个叫做“记录器(Recorder)”的对象。它的作用是记录你的函数调用行为。而后你的函数调用记录会形成一个消息(Message)并放到了队列中,留给COM+的组件去处理。对于客户端程序来说,函数调用会马上返回,线程(THREAD)可以马上进行其它的工作。被调用的函数什么时候正真被COM+内的组件执行则不是客户端程序所需要操心的事了。MSMQ和COM+会把记录了客户端的函数通用行为的消息传达到COM+内的组件那里,COM+内的组件会执行原先客户端程序的函数调用。其过程如下所示:

 

客户端程序 COM+端服务器程序
1.创建对象 1. 创建记录器对象(Recorder Object)
2.调用对象函数 2.记录函数调用
3.释放对象 3.函数调用记录放置到一个消息中
4.继续其它操作 4.消息被放到消息队列中

放置在队列中的消息是由COM+的消息“监听者(Listener)”来处理的。监听者随时观察着消息队列,当有消息被放置到队列中后,它读出这个消息,创建一个队列组件的实例。当这个实例生成后,它就重放原先客户端程序对组件的函数调用过程。

如果函数调用过程中出现了错误,消息处理将被终止,并且这个消息会自动被放置到“再试”队列去。间隔一定时间后,这个消息会再次被处理。如果在“再次处理”过程中,消息仍然出现错误,那么这个消息会被放置到再下一级的“再试”队列中去。这样的“再试”队列共有5级。如果经过这5级后消息仍没有能被成功的处理,那么这个“问题消息”将会被放到“死队列”。管理员必须亲自过问这个消息了。

 

再试次数 时间间隔
一次 1分钟
二次 2分钟
三次 4分钟
四次 8分钟
五次 16 分钟

COM+处理消息的过程如下所示

 

COM+监听者 我们的队列组件
1.监视消息队列   
2.从队列中读取消息   
3.创建对象 1.队列组件的实例被创建
4.重放客户端的函数调用 2.执行函数调用
5.如果出现问题,消息被放置到下一级队列中去。   

 

COM+队列组件的开发

COM+队列组件的开发和其它队列组件的开发过程相似。区别之处在于设置一些队列有关的属性。下面这个小例程是一个比较典型的示例。

using System;
using System.Windows.Forms;
using System.Reflection;
using System.EnterpriseServices;
// 说明COM+应用程序名字
[assembly: ApplicationName("QCSimpleDemo")]
// 说明COM+应用程序的激活方式。对于队列组件,需要采用"服务器"激活方式
[assembly: ApplicationActivation(ActivationOption.Server)]
// 说明COM+应用程序的的钥匙文件名
[assembly: AssemblyKeyFile("QCsimpleDemo.snk")]
// 要使用COM+提供的队列服务,ApplicationQueuing和QueueListenerEnabled两个
// 属性必须设置为 True。这样COM+会自动创建和该COM+应用程序同名的消息队列
// 并且设置在COM+应用程序启动的时候,队列监听者将被创建并监视消息队列,处理消息。
 [assembly: ApplicationQueuing(Enabled=true, QueueListenerEnabled=true)]
// 本例程是在WINDOWS的工作组环境下工作的。在这种网络环境下,消息认证不被支持。为了避免
// 出现"拒绝访问"的错误,在这里"访问管理"被关闭,认证也没有设置。在生产实际中, MSMQ
// 一般是在域(DOMAIN)下工作的,适当的访问管理和认证是必要的。
[assembly: ApplicationAccessControl(Value=false,
                Authentication=AuthenticationOption.None)]
namespace QCSimpleDemo
{
    [InterfaceQueuing]
    // 使用这一属性使得客户端的函数调用可以被放置到队列中去。
    public interface IQComponent 
    {
        void ComplicatedFunction(string parameter)而;
    }
    // 队列组件必须继承ServicedComponent类。同时它还要实现IQComponent接口
    public class QComponent  : ServicedComponent, IQComponent
    {
        public ComplicatedFunction(string parameter)
        {
            //将你的复杂程序放置在这里。这里的程序只是一个示范
MessageBox.Show(parameter, "Message is processed!");
        }
    }
}

 

COM+队列组件的客户端程序开发

在客户端的程序开发中,只有一点要注意,那就是如何生成记录器对象。.NET的System. Runtime.InteropServices中的Marshal类提供了一个静态函数来帮助你生成记录器对象。客户端程序如下所示。

using System;
using System.Runtime.InteropServices;
using QCSimpleDemo;
public class ConsoleClient
{
	public static void Main(String[] args)
	{
		if(args.Length !=1)
		{
			Console.WriteLine("Usage: ConsoleClient message");
			return;
		}
		// 客户端程序不能直接创建队列组件的对象。它将创建一个RECORDER对象来记录客户端
		// 
程序的调用。创建的方法是利用.NET的Marshal类的静态函数BindToMoniker(...)
		// BindToMoniker函数接收一个字符串参数,返回一个相应的对象。
try
		{
			IQComponent iQC = (IQComponent)
                  Marshal.BindToMoniker("queue:/new:QCSimpleDemo.QComponent");
			iQC.ComplicatedFunction (args[0]);
			Marshal.ReleaseComObject(iQC);
		}       
		catch (Exception ex)
		{
			Console.WriteLine("An exception was caught : " + ex.Message 
);
		}
	}
}

 

程序的编译和运行

1.服务器端队列组件

 

步骤 .NET的DOS窗口中的命令
1.生成钥匙文件 sn -k QCSimpleDemo.snk
2.编译源程序 csc /target: library /out:QCSimpleDemo.dll /r:System.
EnterpriseServices.dll /r:System.Windows.Forms.dll /r:
System.dll QCObj.cs
3.注册队列组件 regsvcs QCSimpleDemo.dll
4.安装ASSEMBLY gacutil -i QCSimpleDemo.dll

当你完成上述步骤后,你应该在“组件服务”控制台中看到如下的COM+应用程序:

 

另外,在“计算机管理”控制台中应该看到和COM+应用程序同名的队列以及0-4级5个“再试”队列和“死消息”队列。如下图所示:

 

2.客户端程序

 

步骤 .NET的DOS窗口中的命令
编译源程序 csc /t:exe /out:ConsoleClient.exe /r:QCSimpleDemo.dll /r:System.dll ConsoleClient.cs
运行程序 ConsoleClient Hello_guys

3.启动COM+应用程序

在“组件管理”控制台中选中COM+应用程序,右键单击,在菜单中选取“启动(Start)”,之后你会看到弹出的消息框,表明COM+中的队列组件收到了客户端的消息,并做了相应的操作。

 

COM+队列组件的开发的注意事项

1.队列组件函数设计的问题

队列组件是以异步方式响应客户端的函数调用,客户端程序调用的函数可能在很久以后才会被COM+应用程序处理,所以客户端无法得到函数返回结果。这样,你在设计函数时要注意函数不能设有返回值(VB.NET中只能使用SUB)

2.客户端对消息的控制

如果客户端程序是传统的COM程序,当客户程序释放了记录器(Recorder)的引用后,记录器会将客户端程序的函数调用以消息的形式放到队列里去(本质上讲是记录器的"引用计数器"(Reference Count)为0时)。在.NET里,没有“引用计数器”的概念,那么什么时候消息会被放到队列中呢?

.NET用的是“垃圾清洁工(Garbage Collector)”来回收和管理内存。当记录器的包装对象(Wrapper Object)被回收清理的时候,客户端的函数调用才会被放到队列中去。由于“垃圾清洁工”的工作特性使得消息被放到队列中这一动作有时间上的不确定性。为了加速这一过程,客户端程序可以调用一个函数让让包装对象马上释放记录器。这个函数是ServicedComponet的一个静态函数,叫做DisposeObject()。我们在这里可以对先前的客户程序做一些改进。其核心语句为:

try
{
	IQComponent iQC = (IQComponent)
         Marshal.BindToMoniker("queue:/new:QCSimpleDemo.QComponent");
iQC.ComplicatedFunction (args[0]);
	Marshal.ReleaseComObject(iQC);
	
	ServicedComponent sc = iQC as ServicedComponent;
	If(sc != null)
		sc.DisposeObject(sc);
}

本文旨在通过一个小的例程来介绍一下如何在.NET中使用COM+的队列组件服务。希望给那些频繁使用异步函数调用的程序员一些新的思路。

 

.Net下开发COM+组件

一、问题的提出1、最终用户的每次请求,都将读取Mapping文件--可以通过缓存解决; 2、子系统需要不断的写入Mapping文件--也可以先写入内存然后批量写入文件解决; 二、分析解决问题由于分别有...
  • yellow1234
  • yellow1234
  • 2007年11月02日 18:30
  • 336

COM组件与.Net组件的比较

1、COM组件与.Net组件的比较        COM技术要早于.Net技术。COM定义了一个组件模型,在该模型中,组件可以使用不同的编程语言进行编写,其可以在本地进程中使用,也可以跨进程使用或...
  • Chinamming
  • Chinamming
  • 2013年11月21日 13:47
  • 3519

NET中如何引用COM组件

如果您是初次学习.NET,说不定会尝试着去学习怎样使用COM组件,为了让您少走弯路,我把我所遇到的问题写下来,与大家共享。同时也希望与您一起交流,共同提高。联系方式:电话:0571-88021712 ...
  • lvboliang
  • lvboliang
  • 2007年06月05日 21:15
  • 1248

pb9中COM的创建和调用

  pb中不仅可以调用com(请参见http://blog.csdn.net/precipitant/archive/2007/09/05/1773126.aspx) ,也可以创建com。  创建方法...
  • precipitant
  • precipitant
  • 2007年09月12日 16:15
  • 2570

从COM组件调用.NET 组件

互操作性的优势有时,编程中的革新会使人不得不放弃以前的所有工作。举一个很极端的例子,假设您已有多年 Visual Basic 编程经验,象许多开发人员一样,您当时已建立起一个颇具规模的代码库,而且,由...
  • guxianga
  • guxianga
  • 2007年09月18日 13:11
  • 1279

delphi操作windows COM+组件服务三

在Windwos2000的管理工具里有一个“组件服务”工具,可以实现对COM+组件的应用的安装、启动、删除和对组件的安装、删除。这在安装一个有COM+组件的应用系统时时非常有用的,我们可以通过程序控制...
  • jian704
  • jian704
  • 2008年05月23日 17:22
  • 832

com+组件的注册,卸载和管理

com+打开命令:dcomcnfg 注册和卸载 “Regsvr32.exe”命令是用来对“ActiveX控件”进行注册的。Regsvr32命令格式/u       卸载ActiveX控件/s     ...
  • educast
  • educast
  • 2008年09月05日 21:12
  • 4758

一个com+消息队列的例子

  最近在研究com+和消息队列,于是就做了个例子。   com+和消息队列结构是:  首先服务器端安装com+和消息队列服务器,而客户端安装com+服务的代理和消息队列服务器。   com+和消息队...
  • ILOVEMSDN
  • ILOVEMSDN
  • 2006年08月24日 13:45
  • 1118

无法在com+目录中安装和配置程序集 错误:-2146233087

今天我安装SQL Server2005时碰到了这个错误,到网上搜了一下,找到了解决办法,特记在这里,以备以后需要。  无法在com+目录中安装和配置程序集 错误:-2146233087无法在com+目...
  • surgent
  • surgent
  • 2009年04月04日 16:13
  • 2932

在 vb.NET 中使用 COM+ 服务

 查看原帖2002-04-29 15:33作者: 出处:Microsoft责任编辑:  摘要:将新的 Microsoft .NET 组件添加到现有的 COM 和 COM+ 应用程序中,它们将协同工作;...
  • kenkao
  • kenkao
  • 2009年05月15日 15:27
  • 1822
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:在.NET中使用COM+队列组件
举报原因:
原因补充:

(最多只允许输入30个字)