The problem with the V1 and V1.1 behavior is that depending on the app and the environment in which it is run (is it ngen'd, is it run off a network share, what are the security settings of the machine, etc), the CLR might need to start up COM to perform some of the startup code. When this happens, the CLR needs to start up COM before control enters the user's main and because we need to pick a default, we would CoInitialize it to MTA. What this would cause is that in some situations, your code below that does a CoInitialize in your Main method would fail. However under other circumstances it would pass. Changing the CLR to never use COM before the user's code is executed wasn't possible (it's not impossible, it is just way too much work and puts too many restrictions on the CLR to be viable) so we decided to make the behavior deterministic by always CoInitializing to MTA unless the [STAThreadAttribute] was specified on the main method. Input from Christopher Brumme on this change: "Whenever you set the apartment state of a running managed thread, you are in a race condition. That's because things like .cctors or security demands or assembly load notifications may have executed on that thread, perhaps causing marshaling of oleaut data—or any number of other things that could have caused a CoInitialize to happen. Even if the first line of your managed threadproc sets the apartment state, we have already executed an arbitrary amount of managed application code. And that arbitrary set of code changes whenever you upgrade the CLR, change the JIT inlining, fiddle with .cctor rules for NGEN vs. domain neutral, change security policy, etc. If you are trying to set it to MTA, chances are you are okay. That's because we will default to MTA if we need to CoInitialize a thread. The only way someone would have set it to STA is if a .cctor or security infrastructure or hosting code had done this to you. And that would be pretty rude. Of course, if the CLR sets it to MTA and then the app sets it to MTA, this will be quietly accepted. So the only case that's likely to break is if the application selects STA but the CLR has already CoInitialized the running thread to MTA. Anyway, the bottom line is that applications which set the apartment state of a running managed thread are perched on a knife edge. Long term, we need to move to a more stable and predictable world. The only question is the best way to do this. >We needed to change the behavior of 'main' on a managed EXE to be MTA if it is unspecified and we added a config setting for old C++ apps and for VB/C# apps that weren't built with Visual Studio. The other change we added is for managed threads started with 't = new Thread(...); t.Start();'. If you didn't set the apartment state before you called Start, then it is now too late. We will have already placed you in the MTA. The same config setting to get the old behavior applies here too. We realize that both of these changes will break apps. But those apps are going to break at some rate, as we disturb the race conditions anyway. We are providing the deterministic and reliable behavior now, know it will break some applications, rather than leaving in non-deterministic behavior that breaks applications with each new release." |