Library tutorials & articles

.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}",
                Thread.CurrentThread.ApartmentState);
        }
    }
}

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 =
                ApartmentState.MTA;

            Console.WriteLine("Apartment State = {0}",
                Thread.CurrentThread.ApartmentState);
        }
    }
}

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
InitializeCriticalSectiona
EnterCriticalSection
LeaveCriticalSection
DeleteCriticalSection
lock (C#)
System.Threading.Monitor
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
System.Threading.ManualResetEvent.Reset
ResumeThread System.Threading.Thread.Resume
SetEvent System.Threading.AutoResetEvent.Set or
System.Threading.ManualResetEvent.Set
SetWaitableTimer n/a
Sleep System.Threading.Thread.Sleep
SuspendThread System.Threading.Thread.Suspend
TerminateThread System.Threading.Thread.Abort
WaitForSingleObject and
WaitForSingleObjectEx
System.Threading.Thread.Join or
System.Threading.Monitor.Wait or
System.Threading.WaitHandle.WaitOne
WaitForMultipleObjects and
WaitForMultipleObjects
System.Threading.WaitHandle.WaitAll or
System.Threading.WaitHandle.WaitAny

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.

Comments

  1. 10 Nov 2004 at 21:30
    Greetings-
    I have been doing alot of reading in this area and am frankly confused on which model/classes to use for a specific implementation I am working on. Perhaps you could shed some light.

    I have a large treeview on a UI thread, with nodes that contain collections of images that take a long time to render previews for in a panel. I would like to let a worker thread render the set of previews based on the treeview node selected, passing each preview back to the ui thread as they complete. Of course, it's bad form to have a worker thread access objects in the UI thread.

    I have tried async delegate calls and got it working on the UI thread, but it still locks the UI while it's rendering the previews. I am confused about wether to use events, a ThreadPool, Mutex stuff, or what?

    Can you help me out here?

    Many Thanks
  2. 12 Feb 2004 at 11:57

    hi, interesting article you've written here. just one question, and that is do you know of a function in .NET/C# equivalent to the old PostThreadMessage. The intention here is not to pass any information to a spawned thread via the LPARAM parameter, but rather just to inform the thread of the fact that some information is ready for them to collect (available at a singleton object which is made thread-safe). I tried using the approach of firing events and having the event handled by a delegate but only managed to make this work in the context of the same thread, not across threads. Any ideas?


    Thanks


    Alastair.

  3. 01 Jan 1999 at 00:00

    This thread is for discussions of .NET Threading Part II.

Leave a comment

Sign in or Join us (it's free).

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

Related podcasts

  • A Practical Look at Silverlight 2 Part 1

    Now that Silverlight 2 is at the Olympics and making a big splash, we wanted to explore this fascinating technology more. Microsoft Silverlight 2 is a cross-browser, cross-platform, and cross-device plug-in for delivering the next generation of .NET based media experiences and rich interactive ap...

Events coming up

  • Dec 9

    GL.net Group Meeting - December 2009

    Gloucester, United Kingdom

    The beginning of this year holiday season will belong to mocks. Ronnie and Stephen will take us for a tour around exciting world of unit testing.

Want to stay in touch with what's going on? Follow us on twitter!