Multithreading in .Net and C#

All about multithreading.

Thursday, September 6, 2007

Multithreading on web

I usually refer to Microsoft's msdn library but I often visit following web sites. They have good content on multithreading using .net and C#.

1.Threading in C# by Joseph Albahari
2. msdn
3. Intel software
4. Intel software videos Go to Intel software videos and click on multi-core tab. I suggest you to watch all videos but if you are in hurry, start with Threading in .NET* - Best Practices - 1 to 7 series.

Update:

An interesting article to read.

The Free Lunch Is Over
A Fundamental Turn Toward Concurrency in Software

EventWaitHandler: AutoResetEvent and ManualResetEvent

WaitHandler
Threads can communicate using WaitHandlers by signaling. Mutex, Semapore and EventWaitHandle are derived from WaitHandle class.

EventWaitHandle
There are two types of EventWaitHandlers. AutoResetEvent and ManualResetEvent. AutoResetEvent lets one waiting thread at a time when Set() is called but ManualResetEvent lets all waiting threads to pass by when Set() is called. ManualResetEvent starts blocking when Reset() is called.

AutoResetEvent
This acts like a turnstile which lets one at a time. When a thread hits WaitOne(), it waits till some other thread calls Set(). Take a look at the following picture. Thread1, Thread2 and Thread3 are waiting after calling WaitOne(). For every Set() call from another thread, one thread will pass the turnstile.

I have created a simple application to test this. There are two buttons to span a thread DoWork. DoWork has WaitOne call and it blocks threads. Third button calls Set() to release one thread at a time. Click first two buttons to span thread and click third button twice to release blocked threads.

private EventWaitHandle wh = new AutoResetEvent(false);
private void DoWork()
{
Console.WriteLine(Thread.CurrentThread.Name + ": Waiting for Set() notification");
// Wait for notification
//
wh.WaitOne();
Console.WriteLine(Thread.CurrentThread.Name + ": Notified");
}
private void buttonCreateThreadOne_Click(object sender, EventArgs e)
{
Thread a = new Thread(DoWork);
// You can name the thread!.. for debugging purpose
a.Name = "A";
a.Start();
}
private void buttonCreateSecondThread_Click(object sender, EventArgs e)
{
Thread b = new Thread(DoWork);
// You can name the thread!.. for debugging purpose
b.Name = "B";
b.Start();
}
private void buttonReleaseOneThread_Click(object sender, EventArgs e)
{
wh.Set();
}

Please note that the code after WaitOne call in DoWork is not thread safe. A call to Set will let next waiting thread to enter even the first thread is still executing the code.


ManualResetEvent
This is like a gate which lets more than one at a time. When a thread hits WaitOne(), it waits till someother thread calls Set(). Take a look at the following picture. Thread1, Thread2 and Thread3 are waiting after calling WaitOne(). When Set is called from another thread, all waiting thereads will pass the gate.


Code snippet to illustrate the above.

private void buttonFirstThread_Click(object sender, EventArgs e)
{
Thread a = new Thread(DoWork);
// You can name the thread!.. for debugging purpose
a.Name = "A";
a.Start();
}
private void buttonSecondThread_Click(object sender, EventArgs e)
{
Thread b = new Thread(DoWork);
// You can name the thread!.. for debugging purpose
b.Name = "B";
b.Start();
}
private void buttonCallSet_Click(object sender, EventArgs e)
{
wh.Set();
}
private void buttonCallReset_Click(object sender, EventArgs e)
{
wh.Reset();
}
Download the project.

Wednesday, September 5, 2007

Exception Handling in multithreading

Exceptions occurred in threads will not be caught by global exception handler (implemented at program.cs). These exceptions will take the application down. In the following code snippet, the exception thrown by a thread will take the entire application down. 

// ThreadExceptionForm.cs
private void buttonThreadEx_Click(object sender, EventArgs e)
{
Thread t = new Thread(
delegate()
{
// this Exception will take this application down!
//
throw new Exception("New exception from child thread");
}
);
t.Start();
}

private void buttonEx_Click(object sender, EventArgs e)
{
// This will be caught at global Exception handler
//
throw new Exception("New exception from main thread.");
}


// program.cs
// Global exception handling
//
static void Main()
{
Application.EnableVisualStyles();
Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new ThreadExceptionForm());
}

static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
{
MessageBox.Show(e.Exception.Message, "We caught this one");
}




To avoid this, always surround the thread code with try\catch.

private void buttonThreadTryCatchEx_Click(object sender, EventArgs e)
{
Thread t = new Thread(
delegate()
{
try
{
// this Exception will take this application down!
//
throw new Exception("New exception from child thread");

}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "This was caught at thread's try/catch");
}
}
);
t.Start();
}
download the source code.
 

Tuesday, September 4, 2007

Foreground and Background Threads

1. Foreground threads keep the application alive. But background threads do not keep the application alive on their own. They terminate immediately once all foreground threads have ended.
2. By default threads are foreground threads. Thread can be set as background thread. (thread.IsBackground = true; )

Thursday, August 30, 2007

Multithreaded Singleton: Double-check locking

The following code ensures,

  1. Only one thread can enter the critical area (lock statement)
  2. Only one instance is created and only when the instance is needed (get accessor)
  3. The variable is declared to be volatile to ensure that assignment to the instance variable completes before the instance variable can be accessed. The volatile modifier is usually used for a field that is accessed by multiple threads without using the lock statement to serialize access. Using the volatile modifier ensures that one thread retrieves the most up-to-date value written by another thread.
  4. This uses a syncRoot instance to lock on, rather than locking on the type itself, to avoid deadlocks.
  5. Double-check locking solves the thread concurrency problems while avoiding an exclusive lock in every call to the Instance property method.

The first check avoids an exclusive lock in every call to the Instance property method.
The second check ensures that instance is created only once. Without the second check, check the following scenario.

Thread 1 locks synRoot 
Thread 1 started initializing singleton object.
Thread 2 enters and waits at lock syncroot
Thread 1 finishes the initialization of singleton object and exits.
Thread 2 enters and starts another initialization!

using System;

public sealed class Singleton
{
    private static volatile Singleton instance;
    private static object syncRoot = new Object();

    private Singleton() { }

    public static Singleton Instance
    {
        get
        {

            // First check
            if (instance == null)
            {
                lock (syncRoot)
                {
                    // Second check
                    if (instance == null)
                        instance = new Singleton();
                }
            }

            return instance;
        }
    }
}

More at http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

Wednesday, August 29, 2007

Definitions; Multithreading Interview Questions; Multithreading FAQ

Process and Threads
A process is a collection of virtual memory space, code, data, and system resources. A thread is code that is to be serially executed within a process.

Process always has at least one thread of execution, known as the primary thread. A process can have multiple threads in addition to the primary thread.

Threads vs. Processes
Both threads and processes and they are time sliced with other threads and processes. The key differences are

1. All threads within a single application are logically contained within a process.
2. Processes are fully isolated from each other but threads share the heap memory with other threads running in the same process\application.

Foreground and Background Threads
1. Foreground threads keep the application alive. But background threads do not keep the application alive on their own. They terminate immediately once all foreground threads have ended.
2. By default threads are foreground threads. Thread can be set as background thread. (thread.IsBackground = true; )

Deadlock Condition
A deadlock occurs when each thread is waiting for the other to do something A race condition occurs when one thread finishes before another on which it depends, causing the former to use a bogus value because the latter has not yet supplied a valid one.

Race Condition
A race condition exists when a thread modifies a resource to an invalid state, and then another thread attempts to access that resource and use it in the invalid state

Synchronizing objects
Lock
Locks are useful when only one thread at a time can be allowed to modify data or some other controlled resource.

Monitors
Monitors are Like the lock keyword, monitors prevent blocks of code from simultaneous execution by multiple threads. The Enter method allows one and only one thread to proceed into the following statements; all other threads are blocked until the executing thread calls Exit. This is just like using the lock keyword. In fact, the lock keyword is implemented with the Monitor class.

Mutex
A mutex is similar to a monitor; it prevents the simultaneous execution of a block of code by more than one thread at a time. In fact, the name "mutex" is a shortened form of the term "mutually exclusive." Unlike monitors, however, a mutex can be used to synchronize threads across processes.

Semaphore is same as Mutex but it ensures not more than a specified number of threads can access a resource, or section of code.

Double-check locking for Signleton classes.

More at Multithreaded Singleton: Double-check locking

public sealed class Singleton
{
    private static volatile Singleton instance;
    private static object syncRoot = new Object();

    public static Singleton Instance {
        get {
            if (instance == null) {
                lock (syncRoot) {
                    if (instance == null)
                        instance = new Singleton();
                }
            }
            return instance;
        }
    }
}

Apartments
COM objects in the process as divided into groups called apartments. A COM object lives in exactly one apartment, in the sense that its methods can legally be directly called only by a thread that belongs to that apartment. Any other thread that wants to call the object must go through a proxy.

There are two types of apartments: single-threaded apartments, and multithreaded apartments.

1.Single-threaded Apartments—Single-threaded apartments consist of exactly one thread, so all COM objects that live in a single-threaded apartment can receive method calls only from the one thread that belongs to that apartment. All method calls to a COM object in a single-threaded apartment are synchronized with the windows message queue for the single-threaded apartment's thread. A process with a single thread of execution is simply a special case of this model.

2. Multithreaded Apartments—Multithreaded apartments consist of one or more threads, so all COM objects that live in an multithreaded apartment can receive method calls directly from any of the threads that belong to the multithreaded apartment. Threads in a multithreaded apartment use a model called free-threading. Calls to COM objects in a multithreaded apartment are synchronized by the objects themselves.

Single Instance Application

Single instance application can be implemented using Mutex. Mutex is a synchronizing object that can be used across processes. When the first instance of an application is created, we create a named mutex. In the following attempts we check if the named mutex is already created.

Using remoting, we can send command parameters to the first instance.


private static bool IsRunning()
{
     bool bCreatedNew;


     // Parameters to create Mutex object
     // 1. initiallyOwned = true
     // this gets the calling thread initial ownership of the mutex
     // 2. name of the mutex
     // 3. createdNew
     // When this method returns, contains a Boolean that is true

     // if the calling thread was granted initial ownership
     // of the mutex; otherwise, false.
     // This parameter is passed uninitialized.
     //
     _AppMutex = new Mutex(true, _MutexKey, out bCreatedNew);
     if (bCreatedNew)
          _AppMutex.ReleaseMutex();
     return !bCreatedNew;
}


Download this project.

Blog Archive

About Me

One of my friends said "if you want to learn something, write a book about it". I wanted to learn all about multithreading and instead of writing a book, I am trying to blog. Thank you for stopping. I appreciate your feedback. Sreekanth