10

在实现IComMethodEvents时,您会得到三个事件。

  1. 方法调用
  2. 方法异常
  3. OnMethodReturn

我试图做的目标是记录 COM+ 组件中每个方法的调用时间。

可以通过在COMSVCSEVENTINFOlTime结构中使用和检索事件的时间,因此通过在两者中记录该时间,我应该能够计算调用时间,但我如何确定这两个事件是相关的。lMicroTimeOnMethodCallOnMethodReturn

通过测试它看起来我应该能够使用即时(JIT)激活对象oid

这样做有什么问题还是有其他方法?

一个可能的问题是,我看到oid它经常被重用,所以如果事件由于某种原因被无序触发,实现关联可能会有点困难。

更新1:

进一步的测试表明,这oid在多用户场景中是不够的。同时使用相同的对象,因此必须至少使用oid和来完成相关性original caller。一个后续问题是:如何从 COM+ 事件订阅者那里获取原始调用者?

更新 2:

刚刚找到IComMethod2Events。不同之处在于事件具有执行调用的线程的标识符。在测试中看起来很有希望,我无法想象相关性可能会失败的情况。COM+ 组件的线程模型是Any Apartment.

更新 3

在这篇文章中,使用了创建 COM+ PerfMon 计数器来监视 COM+ 数据 oid。我认为这在多线程公寓中是不够的。

注意:我最终将在 Delphi 中实现这一点,所以我添加了 Delphi 标记。我还添加了 C# 标记,因为用于实现接口的语言很可能根本不重要。更新:暂时添加 c++ 标签只是为了引起以前实际使用过这些东西的人的注意。

4

2 回答 2

3

...如果由于某种原因事件被无序触发...

他们从不这样做。COM+ 系统事件发布者使用 COM+ 事件服务触发这些事件。从事件发布者的角度来看,事件的调用是同步的。当发布者触发一个事件时,它不会继续下一个事件,直到所有订阅者完成对触发事件的处理。很自然,OnMethodReturn/OnMethodException事件在匹配事件之前不会发布OnMethodCall。我记得在 COM+ 事件中阅读过有关竞争条件/中断订阅的 KB。据我所知,所有这些错误都已在 Windows 2000 的各种 Service Pack 中得到解决。不过,诚然,我不会尝试在这方面保持最新状态。

在实现时IComMethod2Events,您订阅与 for 相同的临时订阅IComMethodEvents。所以触发事件的顺序也是一样的。

...因此必须使用至少oidoriginal caller...进行相关性

在这一点上,我真的不确定您是否正确解释了测试结果。你是如何测试的,究竟是什么?

oid应该已经封装了所有需要的信息,即使在具有 JIT 和池的“多客户端”场景中也是如此。上次我实现了这样的事件监听器(已经有一段时间了),依靠oid工作正常。不过,我的环境中的大多数组件都是用 VB6 编写的(因此,住在 STA 中)。然而,即使使用 STA,您也可以在单个线程的不同执行阶段进行多次调用。由于 COM+ STA 线程池中的线程数有上限,您可能会遇到以下情况:调用 A 在特定线程上开始,调用 B 在同一线程上开始,调用 B 返回,调用 A 返回。我不记得在oid没有“有关呼叫者的一些附加信息”的情况下跟踪呼叫有任何问题。

您考虑的实施理念大体上是规范的。COM+ spy平台 SDK 附带的示例使用oid参数来跟踪单个调用。您可以在 中找到应用程序的源代码<Path to SDK samples>\Samples\com\administration\spy。该示例已经使用此实现有一段时间了(至少从 Windows 2003 开始​​)。而今天是 MTA 甚至 COM+ 引入之后的一个世纪。如果有缺陷,样本将在此时更新。希望。

于 2013-04-08T00:14:48.580 回答
1

MSDN 链接“ Creating COM+ PerfMon Counters to Monitor COM+ Data ”似乎与您的目标差不多(尽管我认为在托管 C++ 中)。

相关的部分是这个,我猜:

void IComMethodEvents.OnMethodCall(ref COMSVCSEVENTINFO ei, ulong
    lObjID, ref Guid gClsID, ref Guid gIID, uint nIndex)
{
    //Make sure that monitoring is enabled and that our performance
    //counter has been initialized.
    if (Monitor && pcMethodDuration != null)
    {
    try
    {                    
        //We are going to store the initial value in a Sorted List 
        //collection. To do this we are going to need a key that
        //represents this call.
        string strKey = lObjID.ToString() + gClsID.ToString() + 
            gIID.ToString() + nIndex.ToString();

这可能是您思考 oid(在他们的示例中为 lObjID)的解决方案。不知道这是否涵盖了您的多用户场景,您必须尝试一下。该页面包含有关该主题的很多详细信息,因此希望您能够弄清楚。祝你好运。

于 2013-04-07T16:25:12.443 回答