MSMQ, MessageQueue.Receive, and Thread.Abort

Using MSMQ in a .NET app is incredibly easy – the framework does most of the grunt work for you.  Something that seems fairly natural is to use MSMQ in a Service.

Services are controlled by the Service Control Manager.  When you say “net start myservice”, assuming MyService is installed with the SCM, your service is invoked, and is expected to contact the SCM and wait for commands.  This is handled by the framework so that all you have to do is implement OnStart and OnStop.

Typically OnStart starts a thread, and OnStop signals the thread to stop.  An easy way to signal the thread to stop is to call Thread.Abort on the thread – this raises a ThreadAbortException, which is an exception that can’t be suppressed – you can catch it, but when your catch scope ends, the CLR just throws it again, all the way out until your thread exits.

This is somewhat dangerous obviously (since you can get interrupted anywhere), but if your exception handling is robust then you should be fine, and it’s very easy to implement.

The bummer is that if the purpose of your thread is to receive messages from a MessageQueue and process them, then you’re probably blocking in MessageQueue.Receive.  This is not a .NET function, and Thread.Abort has no effect on it.

You could call MessageQueue.Receive with a timeout, but instead of simply returning failure, the runtime actually throws an exception when the timeout expires – meaning you’d be constantly throwing exceptions as part of your normal operation, something to avoid.

So here’s what you do

IAsyncResult result = queue.BeginReceive();
return queue.EndReceive(result);

Now instead of blocking inside the MessageQueue.Receive function, you’re blocking in WaitOne, which will be woken up by the Thread.Abort.