使用 COM+ 事件

翻译|其它|编辑:郝浩|2004-02-04 11:46:00.000|阅读 1633 次

概述:

# 界面/图表报表/文档/IDE等千款热门软控件火热销售中 >>

COM+ 事件或松散耦合事件 (LCE) 是另一种全新的 COM+ 服务,它面向于使应用程序通过可配置的方式而更具可扩展性。LCE 的主要概念是,将类配置为事件调度员,称为“事件类”。其他有类似接口和方法的类可以配置为订户。每当客户创建“事件类”的实例并调用方法时,COM+ 将发生作用并使所有的订户都接收到该方法调用。与普通“事件”的任何关联(例如 RaiseEventWithEvents 等等)都是纯粹的术语误用。COM+ 事件不与传统 ConnectionPoints 事件关联,并且在完全不同的方案中使用。

有许多方式可以调整这些事件的行为。例如,您可以:

  • 确保这些事件连续或并行触发。

  • 设置过滤器,以便订户只在参数包含它感兴趣的数据时才接收方法调用。

  • 使事件通知通过“排队组件”得到调度。

  • 在运行时添加/删除作为订户的现有对象实例(这称为瞬间订阅)。

  • 实现特殊的接口,它能让您控制以具体样式调度事件的方式。

正如您看到的,所有的灵活性最终都提供可以使用的多种体系结构和实现选项。

要理解“COM+ 事件”的基本原理和查看示例,请阅读以下三篇文章。

COM+ 事件体系结构(英文)
COM+ 事件模式(英文)
COM+ 技术系列:松散耦合事件(英文)

该 MSJ 文章详细说明了大多数 COM+ 事件。

COM+ 事件服务使对数据的发布和订阅更为方便(英文)

不要对多播方案使用 COM+ 事件

开发人员对 COM+ 事件的一个常见反应就是想象一个多播方案,其中服务器端事件(股票值超过 $150)触发无数客户应用程序以显示通知。

但是,COM+ 事件不是设计和构造为处理该方案的。它们同步调用订户,因此大量客户将长时间保留发行者,并且它们需要知道每个订户,使得每个订户的注册和取消注册,对应用程序来说都是必要的。简言之,LCE 不是为它设计的。

在需要通知在远程地点上的大量订户时(如多播方案),通常您不需要知道、也不介意它们是否收到了通知,并且不想等待所有订户收到调用。在这些情况下,另一个号办法是用直接 UDP(基于数据报的 IP 协议)通过网络传递消息。Winsock Control 和 API 使之非常简单。查看下面的链接可以获得更多信息。我们建议使用 API,但如果这样太困难的话,可以代之以 Winsock 控件。

参考

使用 Winsock ActiveX Control 的两个例子 (Q163999)(英文)

理解订户排队的含义

在将订阅标记为排队时,COM+ 将传递把订户看成排队组件的事件。这通常产生预期的行为改变,但是可能产生一些含义。

主要的含义是:

  • 发行者很快继续执行(订户得到同步调用)。

  • 访问检查未立即完成而被延迟。

  • 订户不采用发行者的模拟值。

  • 发行者和订户在不同的事务中运行。

  • 如果后来的错误阻止发行者事务的完成,那么订户不会被调用。

  • 订户将在发行者事务完成并提交之后被调用。

  • 发行者事务不在意订户中发生的任何错误。

  • 有更多的磁盘活动(由事务队列上的 MSMQ 活动引起)。

得出的教训是:正确对待订户属性单上的“排队”复选框,并且使用设计决策而不是性能调整方式。

参考

用排队组件组合事件(英文)

选择适当的 LCE 扩展策略

您的应用程序事件方案可能属于下面的两个种类之一:

  1. 您希望应用程序不管在什么情况下都在执行某个方法调用,并且希望其他订户都只在某些情况下(如果有)执行。在这种情况下,对类的编码可能是完成它的工作,然后调用“事件类”,如图 4 所示。您甚至可以有一个标志(在构造程序或者 SPM 中设置),告诉代码到底是否调用事件。

    图 4. 组件正常执行并且在其处理之前、过程中和其后调用“事件类”。接口不必相同,并且代码正常执行。

    • 在该配置中:

    • 客户调用组件而非“事件类”。

    • 您可更多地控制何时调用事件。

    • 与您的代码需要的相比,“事件类”具备不同的、可能更具体的接口。

    • 您可以决定是否需要在运行时创建“事件类”,以获得更高的性能。

    • 您的代码每次都执行。

  2. 如果需要执行的应用程序与任何将来的订户有同一特性,则需要另一种配置。在某些情况下,甚至可以预见您或客户日后从应用程序中删除特定的订户实现。在图 5 中所述的方案中,预先创建“事件类”并将组件配置为订户可能是最佳选择,即使这样做在性能上会有所降低。

    图 5. 您的组件已经配置为对“事件类”的订户,并且符合事件的接口。您的代码不应取决于订户的执行顺序。

    • 在这种情况下:

    • 客户直接创建和调用“事件类”。

    • 组件必须和任何其他订户一样实现正确的接口/功能。

    • 组件不应取决于被先执行,最后执行,还是中间执行。

    • 一般总是创建“事件类”,即使您的组件是唯一的订户。

您可能还需要实现无数个其他方案。如果是这样,LCE 为发行者、“事件类”和订户以更复杂的方式进行交互提供了机制。请参阅发行者过滤一文(英文),获得详细信息。

不要创建所有的事件

有了所有这些增加的灵活性,就是将所有类配置为“事件类”,并从一开始就添加一个订户都是诱人的。您可以听之任之,并且在需要其他订户的时候添加它们,对吗?别让步。

在创建了类并将它配置为“事件类”后,COM+ 必须介入、从类型库信息中合成正确的接口,并且设置调用订户的内部机制。正如所预期的,这比仅仅创建实际类和调用方法花费的时间更长些。

提前计划,并使 COM+ 事件仅仅来自需要的操作。如果预期某些操作需要 LCE 样式扩展,请创建适当的“事件类”并添加默认订户,或者只在需要时从组件调用“事件类”。

注意参数改变

在调用事件时,调用将传送给所有订户。这些订户对象通常接收有相同参数的相同调用。这是要注意的一个基本方案 — 一旦传送字符串、数组、UDT 或者对象(也就是指向而不是在调用栈中传送的数据类型),并且订户组件改变了值,那么随后的订户都可以看到新值。这将打破订户的独立性概念。

它也会对应用程序带来随机的和意外的问题,特别是并行调用订户时。例如,某个订户可能在其他订户使用数据时更改它。这将会带来崩溃和难以再现的问题。在为订户编码时通过一些规则可以克服该问题。

最普通的方法是将传入参数复制为订户代码中的其他变量。在函数上的所有后续操作都将在副本上进行。请注意对象参数,原因是无法复制整个实例。也不应该将它们设置为 Nothing。这将导致后续的订户试图在稀薄的介质(无效的内存)中操作或执行方法。

缓冲“事件类”创建的代码

正如以前提到的,只要创建了“事件类”,事件接口就是合成的,而且会在幕后发生许多事情。所有这些操作都有您要沿用的相关开销。

操作方式

只要您必须触发多个事件,就这样编码 — 创建一个“事件类”,并在删除前调用多次,而不是一个又一个地连续创建和删除“事件类”。请记住其他准则,例如不要在 SPM 中存储对象、保证对象无状态等等。这些准则优先于该优化方案。


标签:

本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@evget.com


为你推荐

  • 推荐视频
  • 推荐活动
  • 推荐产品
  • 推荐文章
  • 慧都慧问
扫码咨询


添加微信 立即咨询

电话咨询

客服热线
023-68661681

TOP