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 :/
It appears you're using Stephen Toub's
StaTaskScheduler
as a part of some "stateful" logic, where your COM objects live acrossStartNew
boundaries. If that's the case, make sure you create and use these objects on the sameStaTaskScheduler
STA thread and nowhere outside it. Then you wouldn't have to worry about COM marshaling at all. Needless to say, you should createStaTaskScheduler
with only one thread, i.e.,numberOfThreads:1
.Here's what I mean:
If
Obj.Method()
returns another COM objects, you should keep the result in the same StaTaskScheduler's "apartment" and access it from there, too:If you also need to handle events sourced by
Obj
, check this: