Dying Thread on Trackbacks, Referrals and Pingbacks

Part 2 of 2

Bug 2: TrackingHandler Thread Dies

Another problem that Scott Hanselman informed me of was that he would frequently stop receiving Trackbacks, Pingbacks and Referrals on his posts. Furthermore, it was intermittent. This was troubling since losing a Trackback means it's lost forever. Well we went hunting in the code, and thanks to some UnitTest of a theory I had found the answer.

Basically the situation is this. Scott gets a lot of traffic. More than I do. There is a thread in dasBlog that sits around waiting for Trackbacks and the like. You use it by calling trackingQueue.Enqueue(tracking) and then trackingQueueEvent.Set(). So basically dasBlog can sit there and queue a bunch of trackings, and when it's ready the thread runs to execute them. The code looks like this:

private void TrackingHandler( )
{
while ( true )
{
Tracking tracking;

trackingQueueEvent.WaitOne();
while ( true )
{
lock( trackingQueue.SyncRoot )
{
tracking = trackingQueue.Dequeue() as Tracking;
}
if ( tracking != null )
{
try
{
InternalAddTracking( tracking );
}
catch (Exception e)
{
ErrorTrace.Trace(TraceLevel.Error,e);
}
}

if ( trackingQueue.Count == 0 )
{
break;
}
}
}
}

The objects below are created like so:

trackingQueue = new Queue();
trackingQueueEvent = new AutoResetEvent(false);
trackingHandlerThread = new Thread(new ThreadStart(this.TrackingHandler));
trackingHandlerThread.IsBackground = true;
trackingHandlerThread.Start();

So, can you figure out what is wrong? Well I created a unit test that called this 100 times. What I quickly found out was that even though the code was calling break when the trackingQueue.Count was equal to zero the trackingQueueEvent.WaitOne() call wasn't blocking the while loop from continuing. This caused trackingQueue.Dequeue() to throw an unhanded exception (which should have been in a try catch anyway).

Not knowing a whole lot about this kind of threading I looked at a couple of docs and found the answer. Before calling break I added trackingQueueEvent.Reset(). Problem fixed (I hope).