I'm working with a managed service written in C#.
The service interacts with an unmanaged COM object using P/Invoke.
The service supplies the object with a reference to a callback interface.
The object invokes methods on the interface as and when appropriate.
My question: from any point in the service code at runtime, is it possible to determine whether the current thread is executing due to a P/Invoke callback?
In other words, I basically want to do a stack trace and check if the base call was a P/Invoke call back - without any reference to the callback interface or the names of its methods.
Hope that makes sense!
Edit: The reason I asked the question in general terms is because I wanted to know if there was an answer to the question. I know that the design may be... questionable... but at this point I can't see any alternative solution. Here is some more context for the people that might want to offer solutions to my more specific problem.
The issue I'm dealing with boils down to apartments (STA vs MTA).
The COM object is part of an interface for interacting with hardware devices. The service manages multiple hardware devices (ie. multiple instances of the COM object exist at runtime, using the same callback interface).
The service runs in a MTA. The COM object instances also usually run in a MTA (because the object is instanciated by the service). However, in order to interact with certain hardware drivers the COM object must sometimes run in a STA. In those cases the service uses a wrapper class with an internal STA thread to proxy interaction with the COM object instance in the STA. The wrapper uses the same interfaces as the COM object in order to keep one code path.
Most of the time the wrapper solution works fine. The problem is dealing with callbacks from the COM object, because the service needs to invoke methods on the object during the execution of the callback. If you try to proxy those method calls through the STA thread it results in deadlock, presumably because the calls get blocked on the STA message queue (which won't be processed until the callback is completed).
When the STA instances invoke callbacks on the service, P/Invoke executes these callbacks in MTA threads as we'd expect (because the service is running in a MTA). What I didn't expect was that it is possible to directly invoke methods on the COM object during the callback simply by bypassing the proxy thread. Somehow P/Invoke must realise that the thread originated in an object in a STA.
So the crux of the problem is that when dealing with STA, the same methods must be invoked in different ways depending on the context. If the service wants to invoke a method from its own managed MTA threads then it must go through the STA proxy thread; however, if the service wants to invoke that same method during a callback it must invoke the method directly. If I can distinguish between the two contexts then I have a solution for the problem.
Before you suggest... No, it is not practical/possible to pass all the required information as parameters on the callback to avoid the need to call methods during the callback. No, it is not possible to retrieve the required information after the callback is completed. The COM object's context is lost after the callback completes. It would be impractical to try to preserve it.