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; )

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