This is a fairly common pattern, but it has some drawbacks.
First, you should consider using a thread pool (or the .NET parallel libs in 4.0) to process your messages asynchronously. Whether or not your queue reader can be asynchronous depends a lot on your transaction pattern. Will the processing be atomic?
Second, you should also consider using a timer (System.Timers.Timer) which you start in your OnStart and end in your OnEnd, and which reads one or more messages from the queue on each timer event.
Third, you should seriously consider just using the WCF MSMQ binding, which handles a lot of the complexity of this stuff.
See: http://jamescbender.com/bendersblog/archive/2009/04/04/the-one-where-i-talk-about-the-msmq-binding.aspx