实施IComMethodEvents时,您会收到三个事件。
我要做的目标是在COM +组件中记录每个方法的调用时间。
可以使用COMSVCSEVENTINFO结构中的lTime
和lMicroTime
来检索事件的时间,以便在OnMethodCall
和{{1}中记录该时间我应该能够计算通话时间,但我怎么能确定这两个事件是相关的。
通过测试看起来我应该能够使用实时(JIT)激活的对象OnMethodReturn
。
这样做有什么问题或有其他方法吗?
可能存在的一个问题是,我发现oid
经常被重用,所以如果由于某种原因导致的事件无序发生,那么实现相关可能会有点困难。
更新1:
进一步测试表明,oid
在多用户场景中是不够的。同时使用相同的对象,因此必须至少使用oid
和oid
进行相关。后续问题将是:如何从COM +事件订阅者获取原始调用者?
更新2:
刚刚找到IComMethod2Events。区别在于事件具有执行调用的线程的标识符。在测试中看起来很有前途,我无法想象相关性可能会失败的情况。 COM +组件的线程模型为original caller
。
更新3
在本文中,使用了Creating COM+ PerfMon Counters to Monitor COM+ Data Any Apartment
。我不认为这在多线程公寓中已经足够了。
<子> 注意:我最终会在Delphi中实现它,所以我添加了Delphi标记。我还添加了C#标签,因为用于实现接口的语言可能根本不重要。 更新:暂时添加c ++标签只是为了引起之前实际使用过这些内容的人的注意。
答案 0 :(得分:3)
...如果由于某种原因导致的事件无序发生......
他们永远不会这样做。 COM +系统事件发布者使用COM + Events服务触发这些事件。从事件发布者的角度来看,事件的调用是同步的。当发布者触发事件时,在所有订阅者完成已触发事件的处理之前,它不会继续执行下一个事件。很自然地,OnMethodReturn/OnMethodException
事件在匹配OnMethodCall
之前不会发布。我记得在COM +事件中阅读有关竞争条件/破坏订阅的知识库。据我所知,所有这些错误都已在Windows 2000的各种Service Pack中得到解决。但诚然,我并不想在这个领域保持最新状态。
实施IComMethod2Events
时,您订阅与IComMethodEvents
完全相同的临时订阅。所以被解雇事件的顺序也是一样的。
...因此必须至少使用
进行相关oid
和original caller
...
此时我真的不确定您是否正确解释了测试结果。你是如何测试的?
oid
应该已经封装了所需的所有信息,即使在具有JIT和池的“多客户端”场景中也是如此。上次我实现了这样的事件监听器(已经有一段时间了),依靠oid
计算得很好。虽然,我环境中的大多数组件都是用VB6编写的(因此,它们都存在于STA中)。然而,即使使用STA,您也可以通过单个线程在不同的执行阶段进行多次调用。由于COM + STA线程池中存在线程数的上限,因此可能出现以下情况:调用A在特定线程上启动,调用B在同一线程上启动,调用B返回,调用A返回。我不记得在没有“关于来电者的其他信息”的情况下跟踪oid
的来电有任何问题。
您考虑的实施理念大体上是规范的。 Platform SDKs附带的COM+ spy
示例使用oid
参数来跟踪单个调用。您可以在<Path to SDK samples>\Samples\com\administration\spy
中找到该应用程序的来源。该示例已经使用了这个实现很长一段时间(至少从Windows 2003开始)。今天它是MTA甚至COM +介绍之后的永恒。如果存在缺陷,此时将更新样本。希望。
答案 1 :(得分: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)的思考的解决方案。 不知道这是否涵盖了您的多用户场景,您将不得不尝试一下。该页面有很多关于这个主题的细节,所以希望你能够弄明白。祝你好运。