I'm getting very confused about whether C# marshal's COM objects between threads. To this end I have an application which is loading a set of files in a task parallel fashion. I'm using the StaTaskScehduler to load the files using the COM object. Once the COM object is loaded I am storing the object in a central list.
I then later try to perform some processing on this data, again using the STATaskScheduler. However at this point I hit a problem. I receive an exception as follows:
An unhandled exception of type 'System.Runtime.InteropServices.InvalidComObjectException' occurred in MadCat.exe
Additional information: COM object that has been separated from its underlying RCW cannot be used
Now my understanding is that I receive this error because the object hasn't been marshalled into the new thread. I thought this was something C# does for you?
How can I create an apartment threaded COM object in one thread and then use it from another thread?
Am I barking up the wrong tree here? Should I not even be using the Sta apartment for my threads? I can guarantee that the object is never access from multiple threads simultaneously. Any thoughts much appreciated.
Edit: The COM object is defined as follows:
[
coclass,
threading( apartment ),
vi_progid( [Namespace.Class] ),
progid( [Namespace.Class].6 ),
version( 6.0 ),
uuid( GUID_C[Class] ),
helpstring( [Class]" Class" )
]
So by my understanding this is an apartment threaded object, right? I've just tried using a modified task scheduler that doesn't set the apartment state (MTA by default?). This object then does seem to work when I create it in one thread and use it from another. Is this safe or will it come back to bite me some other way?
COM's threading model has always confused the hell out of me :/
Marshal.ReleaseComObject
. But I've never tried to use an STA-threaded COM object on multiple threads, which to my knowledge will not work. That is, you can only use such a COM object on the thread that created it. Also, if it's documented as STA-threaded then it should be used on an STA thread. If you must use the object in this way I think you'll need to add thread synchronization: other threads must request the creator thread to call into the COM object. – AcaulescentMarshal.ReleaseComObject
was called on an instance created from a COM callable wrapper followed by an attempt to call a method on that instance. – Spawnnew StaTaskScheduler(numberOfThreads:1)
does run a dedicated STA thread for the lifetime ofStaTaskScheduler
, untilStaTaskScheduler.Dispose
has been called. Which can be when the app shuts down. If used correctly, it's a perfect home for STA COM objects. – Highness