.NET Threading Part II

COM Interoperability

Now what about those COM apartments? How do these new .NET threads handle COM apartments? .NET threads can reside in both single and multithreaded apartments. When a .NET thread is first started it exists neither in a single-threaded or multithreaded apartment. A static state variable Thread.CurrentThread. Apartment indicates the current apartment type. If you run the code in Listing 4, then the apartment type will be Unknown, as the thread would not have entered an apartment yet.

Listing 4: Threading Model Attributes

using System;
using System.Threading;

namespace ConsoleApplication5
    class Class1
        // line output
        // // Unknown
        // [STAThread] // STA
        // [MTAThread] // MTA
        public static void Main(String[] args)
            Console.WriteLine("Apartment State = {0}",

If you uncomment the line with the STAThread attribute, then the thread set its ApartmentState to STA. If you uncomment the line with the MTAThread attribute, then the thread set its ApartmentState to MTA. This allows control over the apartment type, similar to CoInitializeEx. You can also set the ApartmentState static member directly (see Listing 5).

Listing 5: ApartmentState

using System;
using System.Threading;

namespace ConsoleApplication6
    class Class1
        static void Main(string[] args)
            // Thread.CurrentThread.ApartmentState =
            // ApartmentState.STA;
            Thread.CurrentThread.ApartmentState =

            Console.WriteLine("Apartment State = {0}",

Setting the ApartmentState property has the same affect as using the STAThread and MTAThread attributes.

There are also class attributes that affect the threading model used by the .NET framework. The ThreadAffinity and Synchronization class attributes can be used to synchronize access to a class and its instance members.

[ThreadAffinity()] public class Class1 : ContextBoundObject
[Synchronization()] public class Class1 : ContextBoundObject

When calling into such classes, the calls are serialized to limit access to the class to one thread at any one time. At this point, these class context attributes are really thin on documentation. So, I'll save a more in-depth explanation that may be incorrect anyway.

Win32 to .NET

I figured with all this work I'm doing learning .NET threads that I would leave you with an important resource. Table 1 shows my attempt in converting Win32 functions to .NET classes and methods.

Table 1: Converting Win32 to .NET

Win32 .NET
CreateEvent new System.Threading.Event
CreateMutex new System.Threading.Mutex
CreateSemaphore n/a
CreateThread new System.Threading.Thread and new System.Threading.ThreadStart
CreateWaitableTimer new System.Threading.Timer
lock (C#)
InterlockedCompareExchange System.Threading.Interlock.CompareExchange
InterlockedDecrement System.Threading.Interlock.Decrement
InterlockedExchange System.Threading.Interlock.Exchange
InterlockedIncrement System.Threading.Interlock.Increment
OpenEvent n/a
OpenMutex new System.Threading.Mutex
OpenSemaphore n/a
OpenWaitableTimer n/a
PulseEvent n/a
ReleaseMutex System.Threading.Mutex.ReleaseMutex
ReleaseSemaphore n/a
ResetEvent System.Threading.AutoResetEvent.Reset or
ResumeThread System.Threading.Thread.Resume
SetEvent System.Threading.AutoResetEvent.Set or
SetWaitableTimer n/a
Sleep System.Threading.Thread.Sleep
SuspendThread System.Threading.Thread.Suspend
TerminateThread System.Threading.Thread.Abort
WaitForSingleObject and
System.Threading.Thread.Join or
System.Threading.Monitor.Wait or
WaitForMultipleObjects and
System.Threading.WaitHandle.WaitAll or

If you were to undertake a project of converting a Win32 application to a .NET application, then this table could prove very useful. In some cases, a few objects and methods in the .NET framework could closely emulate a Win32 function. I had to, on occasion, decide how closely they matched and sometimes decided that a match was not appropriate. As an example, you could create a semaphore with a Mutex object and a counter. But I wouldn't say it's a close match, so I didn't mention these instances. In other cases, I had to decide between two matches.

You might also like...


About the author

Randy Charles Morin

Randy Charles Morin Canada

Randy's article are Copyright 1998-2003 Randy Charles Morin

Interested in writing for us? Find out more.


Why not write for us? Or you could submit an event or a user group in your area. Alternatively just tell us what you think!

Our tools

We've got automatic conversion tools to convert C# to VB.NET, VB.NET to C#. Also you can compress javascript and compress css and generate sql connection strings.

“Debuggers don't remove bugs. They only show them in slow motion.”