我正在使用C#编写的托管服务.
该服务使用P/Invoke与非托管COM对象进行交互.
该服务为对象提供对回调接口的引用.
对象在适当时调用接口上的方法.
我的问题:从运行时服务代码的任何一点,是否可以确定当前线程是否由于P/Invoke回调而执行?
换句话说,我基本上想要进行堆栈跟踪并检查基本调用是否是P/Invoke回调 - 没有任何对回调接口的引用或其方法的名称.
希望有道理!
编辑:我一般性地问这个问题的原因是因为我想知道这个问题是否有答案.我知道设计可能......有问题......但此时我看不到任何替代解决方案.以下是可能希望为我的更具体问题提供解决方案的人员的更多背景信息.
我正在处理的问题归结为公寓(STA vs 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对象的上下文将丢失.试图保留它是不切实际的.
小智 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
}
Run Code Online (Sandbox Code Playgroud)