I was using Reflector to peruse some of the source for the .Net ThreadPool, when it showed this:
private static bool QueueUserWorkItemHelper(WaitCallback callBack, object state, ref StackCrawlMark stackMark, bool compressStack)
{
bool flag = true;
if (callBack == null)
{
throw new ArgumentNullException("WaitCallback");
}
EnsureVMInitialized();
if (ThreadPoolGlobals.useNewWorkerPool)
{
try
{
return flag;
}
finally
{
QueueUserWorkItemCallback callback = new QueueUserWorkItemCallback(callBack, state, compressStack, ref stackMark);
ThreadPoolGlobals.workQueue.Enqueue(callback, true);
flag = true;
}
}
// code below here removed
}
The try/finally block struck me as very unidiomatic C#. Why write it like this? What is the difference if you got rid of the try/finally and moved the return to the end?
I understand how Reflector works and that this might not be the original source. If you think that's the case, can you suggest what the original source might have been?
Microsoft has published the source to .NET - though I still use Reflector due to easier browsing. This is the actual code snippet from .NET 4.0.
//
// If we are able to create the workitem, we need to get it in the queue without being interrupted
// by a ThreadAbortException.
//
try { }
finally
{
QueueUserWorkItemCallback tpcallBack = new QueueUserWorkItemCallback(callBack, state, compressStack, ref stackMark);
ThreadPoolGlobals.workQueue.Enqueue(tpcallBack, true);
success = true;
}
Actually, this empty try block and code in finally block pattern is described in the Jeffrey Richter's book "CLR via C#". The thing is that if something goes wrong and thread is aborted the finally blocks are guaranteed to execute. At least they are more likely to execute than try blocks. For more details you should look in the section of mentioned book which describes exceptions and error handling
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With