I found a fun one today. I was working on an ASP.NET page that was having some funny behavior. When you clicked the Search button, instead of being redirected to a search results page, it was going to an error page. I dug into the code and there was not really anything wrong. So, why did I get the error page instead of the results page.
First, a little background: In ASP.NET, I’ve always known that a Response.Redirect
throws a System.Threading.ThreadAbortException
. Whenever I make a web app, and put some air-tight logging mechanisms in it, these show up in my error logs. Even when everything is going as planned, Redirect()
seems to cause an Exception to be thrown.
This is one of those weird examples of why .NET has "Exception"s instead of "Error"s. There is a difference sometimes. This is one of those times.
The reason this gets thrown is because it is your last chance to do something on a thread that is being aborted. Let’s just say, for example that maybe, just maybe, you might have been using an object that needs to be closed/disposed, etc. and it was not in a "Using
" block. For instance, what if you had a COM object, like an office automation object or a custom DLL that makes calls to a USB/Com1 port to communicate with some homemade hardware (for instance). Well, of course, you are awesome and you already know that this should be in a "Using
" block. But let’s just say that maybe you work with some rookies and they are not always attentive. Maybe they make mistakes and you would prefer to not give them an opportunity to make a mistake that will hang your web server. The next time that one of those well-meaning rookies plops a Response.Redirect()
right in the middle of nowhere, you will be lucky, because you had a Try
/Catch
block and you caught the thread abort (just in case) and did a Dispose()
, if you still needed to.
So, in other words, the System.Threading.ThreadAbortException
is like a "last call" for Dispose()
or some other clean-up code. There are probably nicer ways to handle it, but if you don’t want to take that chance, this little gem will catch your leaks.
Most of the time (nearly all of the time), you don’t need this and you don’t need to care. You could just ignore it, but the perfectionist in me wants to fix them. After all, they are exceptions. Exceptions are bad. …Must…fix…
So, if you are like me, and you want perfection in your error logs, here is what you do:
try
{
}
catch (System.Threading.ThreadAbortException tae)
{
}
Now your ultra error handler logs will not get crammed full of trivial non-errors.