GOTCHA 68 Default apartment of main thread is inconsistent across languages


GOTCHA #68 Default apartment of main thread is inconsistent across languages

In Example 8-3 you first marked the Main() method with the STAThread attribute, then in Example 8-4 changed it to MTAThread. What is the apartment if you do not mark Main() with either attribute? The answer, unfortunately, depends on which language you are using. Consider Example 8-5.

Example 8-5. Default apartment

C# (DefaultApartment)

 using System; using System.Threading; namespace COMCompUser {     class Test     {         static void Worker()         {             Thread currentThread = Thread.CurrentThread;             Console.WriteLine("In worker thread");             Console.WriteLine("Apartment in worker is {0}",                 currentThread.ApartmentState.ToString());             Console.WriteLine("Creating COM object");             MyCOMCompLib.IMyComp theMyComp                 = new MyCOMCompLib.MyCompClass();             Console.WriteLine("Apartment in worker is {0}",                 currentThread.ApartmentState.ToString());         }         static void Main(string[] args)         {             Thread currentThread = Thread.CurrentThread;             Console.WriteLine("Apartment in main is {0}",                 currentThread.ApartmentState.ToString());             Console.WriteLine("Creating COM object");             MyCOMCompLib.IMyComp theMyComp                 = new MyCOMCompLib.MyCompClass();             Console.WriteLine("Apartment in main is {0}",                 currentThread.ApartmentState.ToString());             Thread workerThread = new Thread(                 new ThreadStart(Worker));             //Not setting IsBackground on thread intentionally             workerThread.Start();         }     } } 

VB.NET (DefaultApartment)

 Imports System.Threading Module Test     Private Sub Worker()         Dim currentThread As Thread = Thread.CurrentThread         Console.WriteLine("In worker thread")         Console.WriteLine("Apartment in worker is {0}", _                  currentThread.ApartmentState.ToString())         Console.WriteLine("Creating COM object")         Dim theMyComp as MyCOMCompLib.IMyComp _                 = new MyCOMCompLib.MyCompClass()         Console.WriteLine("Apartment in worker is {0}", _          currentThread.ApartmentState.ToString())     End Sub     Public Sub Main()         Dim currentThread As Thread = Thread.CurrentThread         Console.WriteLine("Apartment in main is {0}", _          currentThread.ApartmentState.ToString())         Console.WriteLine("Creating COM object")         Dim theMyComp as MyCOMCompLib.IMyComp _                 = new MyCOMCompLib.MyCompClass()         Console.WriteLine("Apartment in main is {0}", _          currentThread.ApartmentState.ToString())         Dim workerThread As New Thread(AddressOf Worker)         'Not setting IsBackground on thread intentionally         workerThread.Start()     End Sub End Module 

In this example, the apartment attribute is not set on the Main() and Worker() methods. When you execute the code, the output differs between the languages. The output from the C# version is shown in Figure 8-8; the VB.NET output appears in Figure 8-9.

Figure 8-8. Output from the C# version of Example 8-5


Figure 8-9. Output from the VB.NET version of Example 8-5


As you can see, the apartment of Main() is different between the C# and VB.NET versions. This is because in C#, if you don't set either STAThread or MTAThread, the apartment is first unknown. Once you access the COM component, it is set to MTA. In VB.NET, however, if you don't set either of the attributes, the compiler sets the STAThread automatically for Main(). (You'll see this if you view the MSIL for Main() with ildasm.exe.) But the apartment of the worker thread, i.e., the apartment within the Worker() method, is MTA for both languages. So the apartment of the Main() tHRead defaults to different values depending on the language used. This can be troublesome to programmers who have to maintain code in both languages.

IN A NUTSHELL

Understand the apartment in which your thread is running. Don't assume or depend on the defaults. Set it explicitly to the desired value.

SEE ALSO

Gotcha #67, "Cross-apartment calls are expensive," Gotcha #69, "STAThread attribute may have no effect on your methods," and Gotcha #70, "Spattering access to COM components makes code hard to maintain."



    .NET Gotachas
    .NET Gotachas
    ISBN: N/A
    EAN: N/A
    Year: 2005
    Pages: 126

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net