.NET COM threading model

  • Thread starter Thread starter Martin Plechsmid
  • Start date Start date
M

Martin Plechsmid

Hello,

I have a MFC application that uses a COM object implemented in .NET
(C++/CLI). The COM object behaves as if it uses the SLA COM threading model
(i.e. serialized access). How to change the threading model to MTA
(concurrent access)?

The COM code looks like this:

[ComVisible(true)]
[Guid("<COM interface GUID>")]
[InterfaceType(ComInterfaceType::InterfaceIsDual)]
public interface class IPdfReport
{
public:
String ^GetPdf(<arguments>);
}

[ComVisible(true)]
[Guid("<COM class GUID>")]
public ref class PdfReport : public IPdfReport
{
public:
virtual String ^GetPdf(<arguments>);
}

There exists System.MTAThreadAttribute class. But according to
documentation, it can be applied to the Main() method of an application
only, not to a class.
Any hint?

Thank you,
Martin.
 
Martin said:
Hello,

I have a MFC application that uses a COM object implemented in .NET
(C++/CLI). The COM object behaves as if it uses the SLA COM threading model
(i.e. serialized access).

Can you elaborate on what "behaves as if" really means? What exactly
are you observing?
How to change the threading model to MTA
(concurrent access)?

I'm not a COM expert, but my understanding is that a managed "COM
visible" object is either STA or MTA depending on what apartment model
the thread that creates the object is (i.e. the COM visible managed
objects are all threading model "Both"). If true, then you simply have
to make sure you don't create the object on an STA thread, if you want
MTA behavior.
[...]
There exists System.MTAThreadAttribute class. But according to
documentation, it can be applied to the Main() method of an application
only, not to a class.

Right. The attribute is applicable for entry points only because it's
used by the run-time for that particular purpose. As the docs for that
class explain, if you need to set the attribute for other threads, you
need to create the Thread instance and then call
Thread.SetApartmentState() before the thread actually starts.

That said, MTA is the default for a thread, whether the main thread or
one created later. So in reality, normally one just uses the
STAThreadAttribute attribute, or calls SetApartmentState() with the
ApartmentState.STA value.

Relating back to your original question: I think that if you create your
COM object using a thread that hasn't been explicitly set as STA (either
because it's the main thread of a Forms, WPF application, or other type
of program where [STAThread] has been applied to the entry point, or
because it's a thread that's been created later and set to
ApartmentState.STA before it started), you should find it behaves as an
MTA object.

Of course, this means your object will be responsible for dealing with
all concurrency synchronization issues itself. But I'm guessing you
know that already. :)

Pete
 
Hello

and yes, you are right, the threading model of the .NET COMs is "both":

HKCR\CLSID\<guid>\InprocServer32\ThreadingModel = "Both"

And I found calls of ::CoInitialize(NULL) in the C++ COM client code, which
implicitly chooses the STA model.
I'll change it to ::CoInitializeEx(NULL,COINIT_MULTITHREADED), this should
solve the thing.

Thank you for your response, it helped to point me in the right direction.
Martin.
 
Back
Top