Antuan Kinnard

in
Mutex and Semaphore WaitHandles: An Overview

I am willing to bet that every developer has been warned about the dangers of developing multi-threaded operations at some point in their career. Let's face it, we have enough to worry about with apps behaving oddly as a result of client machine setup, network configuration, and authorization changes than to let the complexities of threading be added to the list. It's not that it’s such a difficult subject to grasp, but there is plenty to understand in order to create a successful robust implementation. As we all know, the biggest reasons that many will advise careful consideration are well-founded because of its unpredictable nature. Among other issues - like recovering from errors - the complexity of operations happening at the same time is not always very appealing to the developer. You need a way to 'synchronize' threads so that one is not stepping on the other's toes. One attractive way to tackle this problem is the use of waithandles.

The WaitHandle class is located in the System.Threading namespace. Waithandles allow you to manage when, how, and how long a thread will block and wait for access to a piece of functionality. This is done by signaling (or notifying for you Java coders) another thread when the current thread is done. The WaitHandle waits to be signaled when one of the static wait methods - WaitOne(), WaitAny(), or WaitAll() - is called. The WaitOne() method will block all other threads until it is signals them to continue. Along with the timeout parameter, the WaitAll and WaitAny methods take WaitHandle arguments that are used to signal and unblock any waiting threads. Until the waiting threads are signaled (or the timeout is reached), the threads will wait. If you’re developing a process which requires simultaneous access to some shared resource, your implementation should begin with determining how shared the resource should be. When this is done, you can explore a couple more options.

Derived WaitHandles: Mutexes and Semaphores

The Mutex and Semaphore classes are derived from the WaitHandle class. With extra functionality than WaitHandle, they can give you a more scalable solution. Unlike Monitors, these waithandles can be named and accessed across the operating system. Using the OpenExisting() methods, you can access the specified named mutex or semaphore. I like that along with these waithandles, you also get access control security to implement when using it across application domains. You control security by using .NET 2.0's new SetAccessControl() method and the SemphoreSecurity and MutexSecurity classes. Take a look through Microsoft’s documentation on these classes for more information.

As descendants of the WaitHandle class, mutexes and semaphores signal the blocking thread for synchronization using the ReleaseMutex() and Release() methods, respectively. The first thread entering the code ‘locks’ the functionality with a simple call to the WaitOne() method. So what’s the difference between the two, you ask? The answer is that semaphores can count. When the WaitOne() method is called on multiple threads using the same mutex, only the first thread to call the method will continue on while the other threads wait for it to signal that it’s done. Once it’s done, the next one will gain access and the rest will remain blocked, and so on down the line. On the other hand, when the WaitOne() method is called using a semaphore, it will not cause any other thread to be blocked until a zero count is reached. You declare the max count with the call to the constructor. So each time the WaitOne() method is called, the semaphore count decrements by one until 0 is reached. Any other thread blocking at the WaitOne() line will enter the semaphore as the count increases. Depending on your implementation, semaphores can give you even more flexibility and scalability. And what architect wouldn't want that?

Let’s take a look at a couple of examples of how mutexes and semaphores lock:

Mutex Example

using System;
using
System.Threading;

namespace MutexExample {
    public class MutexTest {
        private const int MAX = 5;
        private Mutex _mutex;
        private int _count = 0;

        public void Run() {
            _mutex = new Mutex();           

            for (int i = 0; i < MAX + 2; i++) {
                Thread t = new Thread(new ThreadStart(Start));
                t.Start();
            }
       
}

        private void Start() {
            string name = "Thread " + _count++;

           
_mutex.WaitOne();

           
Console.WriteLine("{0} : Entering mutex", name);
       
    Thread.Sleep(3000);
            Console.WriteLine("{0} : Exiting mutex", name);

           
_mutex.ReleaseMutex();
        }
    }
}

Semaphore Example

using System;
using
System.Threading;

namespace SemaphoreExample {
    class SemaphoreTest {
        private const int MAX = 5;
        private Semaphore _semaphore;
        private int _count = 0;

       
public void Run() {
            _semaphore = new Semaphore(MAX, MAX);

           
for (int i = 0; i < MAX + 2; i++) {
               
Thread t = new Thread(new ThreadStart(Start));
               
t.Start();
           
}
       
}

        private void Start() {
            _semaphore.WaitOne();
            string name = "Thread " + _count++;

           
Console.WriteLine("{0} : Entering semaphore ", name);
           
Thread.Sleep(3000);
           
Console.WriteLine("{0} : Exiting semaphore ", name);

           
_semaphore.Release();
       
}
    }
}

As you can see from these examples, mutexes and semaphores are very simple to use. However, the same may or may not be said when actually putting them to good use, and debugging them. If you’re anything like me, you’re probably already thinking about 2 or 3 instances where these WaitHandles could have helped. If you’re even more like me, you’re probably thinking, “Why would I ever use a mutex over a semaphore.” I would answer, “If you asked that question, you probably wouldn’t.” Most smart developers will adhere to the ever-present goal of creating scalable solutions where the only bounds are that of the programming language. While this may sound facetious, the fact remains that mutexes only allow access to one thread, while semaphores can be much more flexible.

Fun with the Rebel

After almost a year of debating whether I should or shouldn't, I finally purchased my first dSLR camera - the Canon EOS 350D a.k.a. Digital Rebel XT. I've been doing a ton of photography research and kept saying that I'd get it one day. Well, I finally put my money where my mouth is. Turns out that putting your money where your mouth is can be more expensive than you would think. I thought I could just purchase the camera, a lens, and some memory (256 at the most). Although you could work with this, you will most likely want to upgrade and expand your inventory soon if you're serious.  Upon purchase, I got the camera, 2 lenses, memory, and a tripod. I still needed a lens hood, polarizer, UV filter, ND filter, more memory, flash, camera bag and a few other things.  I never knew that there were so many things to buy.

My first milestone was actually deciding on which camera. All along I knew that the Rebel was the camera I was going to get but then I thought I'd take a look around.  I looked at the Nikon D50, the Nikon D70s and the Canon EOS 20D. My decision suddenly became a little more difficult as the Nikons are much cheaper than their Canon counterparts. In the end, I chose the Rebel because 1) the Nikons were 2 megapixels less than the Rebel (this is a big deal because I do a fair amount of cropping) and the 20D was about $400 more than the Rebel.

One of the biggest challenges was finding a decent 'walk around' lens. A walk around lens would allow me to take a large range of pics without changing lenses all the time. Being new to photography, this was a daunting task as there are so many lenses, lens reviews and lens tests out there. And if that wasn't enough, I came across some tests which were done incorrectly yielding incorrect results. So to start, I came up with a list of things I had to have without compromising image quality too much. After a few iterations, my lens requirements simply came down to:

  1. good image quality
  2. good performance in low light situation
  3. wide angle range
  4. decent telephoto range
  5. all-purpose (for those times when I don't wanna carry around a ton of lenses)
  6. not too expensive

After all my research, I finally decided on the Canon 28-135mm f/3.5-5.6 IS USM and Canon 50mm 1.8 lenses. The 28-135 addresses numbers 1, 4, 5 and somewhat 6 requirements while the 50mm addresses 1, 2 and 6. Even though I haven't addressed 3 yet, I was very successful in meeting my requirements overall.

For my budget, I think I made some good decisions. Without going into any technical details, image quality has been very good from what I've seen so far. All of the problems I've seen so far has been user error (go figure). In an attempt to get more comfortable with it, I took it on a test run to the 2006 Chicago Auto Show. It performed really well and I actually enjoyed snapping away. Since I obviously picked the worst day to go to the show so I wasn't able to get too creative as I kept it on Av Mode most of the time. One of the good things about dSLR cameras is that the images they produce can take a good deal of punishment (without losing losing much image data) from Photoshop, GIMP, Paint.NET, or whatever you use. Good thing too because I didn't set the correct white balance (causing red and/or yellow casts) and had to adjust my pics through photoshop. If I had had a larger memory card, I could have shot in RAW format and changed the white balance after the fact without any loss in image data. I'm not an expert yet, but you can take a look at a few of my first Rebel pics at the Chicago Auto Show. 


Posted: Feb 17 2006, 03:36 PM by akinnard | with no comments
Filed under: ,
Sending Mail in .NET 2.0

I'm going to start off by admitting that it's been a while since I had to write any code that supported sending email. Back when I was a corporate Java/JSP developer, support for sending email was built into almost every application's framework that we wrote. We chose email as our 'notification service' because it was easier than writing Java code which allowed users and developers to receive notifications any other way. They needed a non-intrusive way to receive these notifications which meant we couldn't install any applications. Email did just that. Now as a (mostly) .NET developer, I haven't worked on any applications requiring such an architecture. Regardless, I found myself playing around with .NET's mail classes. While they are no JavaMail classes, they've been given some attention by the Microsoft developers in the .NET Framework version 2.0. For starters, the classes in the System.Net.Mail namespace - formerly System.Web.Mail - are no longer wrappers for CDOSYS. They've been re-worked from the ground up and given more functionality.

Sending email is just as simple as it's always been in the .NET Framework. It only takes about 5 to 6 lines of code to construct a message and send it off to the SMTP server. The object that sends the message has been renamed from SmtpMail to SmtpClient - a more appropriate name if you asked me. To send the message, you can use the SmtpClient.Send method which has the same signature as the previous version's. In addition to sending the message using the Send method, we also have the option of sending mail asynchrounously. Using the SmtpClient.SendAsync method, the application will not be blocked as it is with the Send method. I'm sure some developers will see this as a bell and/or whistle since using a separate thread would be just as simple. However, I think it's cool to have this functionality right out of the box. After all, aren't the bells and whistles the reasons we're all writing .NET code? Let's look at a simple example of sending email using SendAsync.

using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Net.Mail;
using System.Net.Mime;
using System.ComponentModel;

namespace SimpleMail {
    class SimpleMail {
        private SmtpClient _smtpClient = null;

        public SimpleMail() {
            _smtpClient = new SmtpClient("MyRelayServer.com", 25);
        }

        public void SendAsynchronousMail(
            string toAddress,
            string fromAddress,
            string messageBody,
            string subjectText,
            IDictionary<string, Stream> attachmentStream,
            string token /* UserState */
            ) {

            //create the message
            MailMessage msg = new MailMessage(fromAddress, toAddress);
            msg.Body = messageBody;
            msg.Subject = subjectText;


            //add the attachment(s)
            if (attachmentStream != null) {
                foreach (string s in attachmentStream.Keys) {
                    Attachment
attachment = new Attachment(attachmentStream[s], MediaTypeNames.Application.Octet);
                    attachment.Name = s.ToString();
                    msg.Attachments.Add(attachment);
                }
            }

            //send an email to the reply address of any failures after all retries
            msg.DeliveryNotificationOptions =
DeliveryNotificationOptions.OnFailure;

            //attach the delegate to handle the callback

            _smtpClient.SendCompleted +=
new SendCompletedEventHandler(this.SendCompleted);

            //send the message and return immediately

            _smtpClient.SendAsync(msg, token);


            //TODO: Do not close the stream

        }

        private void SendCompleted(object sender, AsyncCompletedEventArgs e) {
            if (e.Cancelled)
                Console
.WriteLine("The message [{0}] was canceled.", e.UserState.ToString());

            if
(e.Error != null) {
                StringBuilder errorMsg = new StringBuilder();
                errorMsg.Append(
string.Format("An error occurred sending message [{0}]. {1}", e.UserState.ToString(), e.Error.Message));

                if
(e.Error.InnerException != null)
                    errorMsg.Append(
Environment.NewLine + "Inner exception message: " + e.Error.InnerException.Message);
                   
                Console
.WriteLine(errorMsg);
            }
else {
                    Console
.WriteLine("Message [{0}] sent.", e.UserState.ToString());
            }
        }

        public void CancelMail() {
            _smtpClient.SendAsyncCancel();
        }
    }
}

As you'd expect, an event handler has been added for the callback as well as an identifier, or token, for the message sent. SendCompletedEventhandler sends the AsyncCompletedEventArgs object to the SendCompleted callback method. As shown in the example code, you can use AsyncCompletedEventArgs to determine if an error occurred while sending and if the message was canceled. The UserState property will be populated with the token object that was passed to the SendAsync method.

Along with the SendAsync method comes the SendAsyncCancel method. Can anyone guess what this does? That's right, cancels the message. However, don't expect it to cancel a message that the server has already queued. Once it's there, you won't be able to use the SendAsyncCancel method to remove it from the SMTP queue.

Another change worth mentioning is more options for sending attachments. With the 2.0 version of the framework, developers now have the option of sending attachments directly from a stream. So you no longer need a file to send from because anything from a MemoryStream to a CryptoStream can be sent directly from the stream itself. Be sure if you're using a stream with the SendAsync method that you don't close the stream before the send operation is done sending the message to the server. This will cause an SmtpException exception since the method is not actually done with the stream. This leads me to my next point: When checking exceptions thrown by these classes, be sure to check the inner exception. I'm sure I don't need to tell anyone this because we all check our inner exceptions. *cough* This is an invaluable tip for anyone using this namespace. In the case of prematurely closing memory streams that is being sent as an attachment, the first exception in the chain is an SmtpException with the message, "Failure sending mail." Not very informative to those of us without psychic abilities, eh? Checking the inner exception will yield a NotSupportedException exception and the message, "Stream does not support reading."  So check and log those inner exceptions!

Now for the all-important question, "How do I receive email?" Short answer is that you can't receive email using the System.Net.Mail namespace. This is one area I think JavaMail has got .NET beat. That said, if you're up for the challenge you can write your own communication with your POP and IMAP store using sockets. If you're not up to this challenge, there are a number of components written that can save you some time here and here.

There's a lot more functionality in the System.Net.Mailnamespace that should be explored. Sending email through SSL, sending alternate ways to view the message, and delivery notifications are a few more areas worth taking a look at.  To help get you started, you can check out Dave Wanta's site at http://systemnetmail.com.  This is a pretty good FAQ about the namespace.  If you'd like a comparison with the .NET 1.1, check out http://systemwebmail.com.