检测是否从P/Invoke调用
本文关键字:Invoke 调用 是否 检测 | 更新日期: 2023-09-27 18:04:42
我正在使用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对象的上下文丢失。想要保存它是不现实的。
是否有帮助
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
}