2

There are those [MTAThread] and [STAThread] attributes which control the apartment threading model for COM in .Net applications, and from my own (very limited) testing, CoInitializeEx() returns 1 (S_FALSE) if called from the main thread of a console C# application.

According to Microsoft documentation, S_FALSE means "The COM library is already initialized on this thread".

What I am wondering is whether there is actually a contractual guarantee in the framework itself that COM is going to be initialized on every .Net (Framework or Core application) thread?

If so, is it also guaranteed that all threads will be initialized with the same (STA or MTA) model?

I am asking this because for DirectShow applications it is crucial that COM is initialized on every thread, and I would like to avoid peppering the code with redundant calls to CoInitializeEx() and CoUnitialize() if those are already implicitly handled by the framework.

Igor Levicki
  • 1,017
  • 10
  • 17
  • Obviously it won't be guaranteed for all core applications, since they won't actually be running on a system that knows what COM even is. But I assume you're limiting yourself to .NET apps running on Windows. – Damien_The_Unbeliever Nov 26 '21 at 15:09
  • Thread pool threads are MTA since they have to be ready for anything. Your own entry point should be marked with appropriate attribute, and any threads you explicitly create can have the apartment state set before starting. I'm not sure what other threads you'd need to think about where some default would be required. – Damien_The_Unbeliever Nov 26 '21 at 15:13
  • [Some hints of documentation about this on Old New Thing](https://devblogs.microsoft.com/oldnewthing/20150316-00/?p=44463). Unfortunately, whatever documentation is being quoted isn't linked to from either post – Damien_The_Unbeliever Nov 26 '21 at 15:41
  • https://stackoverflow.com/questions/4154429/apartmentstate-for-dummies/4156000#4156000 – Hans Passant Nov 26 '21 at 19:47
  • @Damien_The_Unbeliever Yes, I am limiting this to apps running on Windows because COM and technologies that rely on it such as DirectShow, DirectX, Direct2D, DirectWrite, etc are Windows only. – Igor Levicki Nov 27 '21 at 12:01
  • @HansPassant Thanks for the additional info. The only remaining issue I have is that some sources say you should use MTA, and some say "to avoid trouble use STA for DirectShow fitergraph creation, run/pause, and destroy". Now I don't know which is correct, and if STA is really required then how to change default model for threads? – Igor Levicki Nov 27 '21 at 12:12
  • 1
    You don't like trouble. Use Thread.SetApartmentState(). By far the best approach is to ensure it just doesn't matter, don't make calls from another thread and you never have to worry about thread-safety. If that's unavoidable for some reason then use .NET's mechanisms to marshal the call. [Example](https://stackoverflow.com/a/21684059/17034). – Hans Passant Nov 27 '21 at 12:36
  • 1
    `how to change default model for threads?` You would have to use the lower level `Thread` class and call [`Thread.SetApartmentState()`](https://learn.microsoft.com/en-us/dotnet/api/system.threading.thread.setapartmentstate?view=net-6.0) before starting the thread. NOTE: This would NOT be a threadpool thread. – Matthew Watson Nov 27 '21 at 14:37

1 Answers1

2

The documentation states that threads from the Managed Thread Pool are

in the multithreaded apartment

The documentation for Task.Run() also states that it

Queues the specified work to run on the ThreadPool

(ThreadPool in this case being the Managed Thread Pool.)

Finally, the documentation for class Thread's obsolete ApartmentState property states that

In .NET Framework version 2.0, new threads are initialized as ApartmentState.MTA if their apartment state has not been set before they are started.

That covers pretty much all of the managed ways to create a thread.

You could of course slap an [MTAThread] attribute on your Main() method too, but even that's not necessary because the default for the main entry point is MTA too.

So at the end of the day - unless you're calling any unusual third-party code, you can pretty much be guaranteed that your threads will be MTA.

Matthew Watson
  • 104,400
  • 10
  • 158
  • 276