检测是否从P / Invoke调用

时间:2014-05-23 12:27:45

标签: c# pinvoke

我正在使用C#编写的托管服务 该服务使用P / Invoke与非托管COM对象进行交互 该服务为对象提供对回调接口的引用 该对象在适当的时候调用接口上的方法。

我的问题:从运行时服务代码的任何一点开始,是否可以确定当前线程是否由于P / Invoke回调而正在执行?

换句话说,我基本上想要进行堆栈跟踪并检查基本调用是否是P / Invoke回调 - 没有任何对回调接口或其方法名称的引用。

希望有意义!


编辑: 我一般性地问这个问题的原因是因为我想知道这个问题是否有答案。我知道设计可能......有问题......但在这一点上,我看不到任何其他解决方案。以下是可能希望为我的更具体问题提供解决方案的人员的更多背景信息。

我处理的问题归结为公寓(STA与MTA)。

COM对象是用于与硬件设备交互的接口的一部分。 该服务管理多个硬件设备(即,运行时存在多个COM对象实例,使用相同的回调接口)。

该服务在MTA中运行。 COM对象实例通常也在MTA中运行(因为该对象由服务实例化)。但是,为了与某些硬件驱动程序交互,COM对象有时必须在STA中运行。在这些情况下,服务使用具有内部STA线程的包装器类来代理与STA中的COM对象实例的交互。包装器使用与COM对象相同的接口,以保留一个代码路径。

大多数情况下,包装器解决方案正常工作。问题是处理来自COM对象的回调,因为服务需要在执行回调期间调用对象上的方法。如果您尝试通过STA线程代理这些方法调用,则会导致死锁,大概是因为调用在STA消息队列上被阻塞(在回调完成之前不会被处理)。

当STA实例调用服务上的回调时,P / Invoke会像我们预期的那样在MTA线程中执行这些回调(因为服务在MTA中运行)。我没想到的是,只需绕过代理线程就可以在回调期间直接调用COM对象上的方法。不知何故,P / Invoke必须意识到线程起源于STA中的一个对象。

问题的关键在于,在处理STA时,必须根据上下文以不同的方式调用相同的方法。如果服务想要从其自己的托管MTA线程调用方法,那么它必须通过STA代理线程;但是,如果服务想要在回调期间调用相同的方法,则必须直接调用该方法。如果我可以区分这两种情况,那么我就可以找到问题的解决方案。

在你建议之前...... 不,在回调中传递所有必需信息作为参数是不实际/不可能的,以避免在回调期间调用方法。 不,在回调完成后无法检索所需信息。回调完成后,COM对象的上下文将丢失。试图保护它是不切实际的。

1 个答案:

答案 0 :(得分:0)

这有用吗

using System.Diagnostics; 

StackTrace stackTrace = new StackTrace();           // Get call stack
StackFrame[] stackFrames = stackTrace.GetFrames();  // Get method calls (frames)

// write call stack method names
foreach (StackFrame stackFrame in stackFrames)
{
    Console.WriteLine(stackFrame.GetMethod().Name); // Write method name
}