Library tutorials & articles
.NET Threading Part II
- Introduction
- ReaderWriterLock
- Mutex & Local Thread Storage
- COM Interoperability
- Thread States
- Background Threads
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.
Related articles
Related discussion
-
Binary Studio | software development outsourcing Ukraine
by shane124 (4 replies)
-
Chart insertation in a windows form...
by pdhanik (1 replies)
-
Point of Sale Developers: Hardware & C# SDK
by ManiGovindan (7 replies)
-
help with the remote frame buffer protocol from real VNC
by poison (0 replies)
-
Need help making a complete program editable, C# or .net I think
by davelee (1 replies)
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.
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
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.
This thread is for discussions of .NET Threading Part II.