The ThreadAbortException is thrown when you make a call to Response.Redirect(url) because the system aborts processing of the current web page thread after it sends the redirect to the response stream. Response.Redirect(url) actually makes a call to Response.End() internally, and it's Response.End() that calls Thread.Abort() which bubbles up the stack to end the thread.
//An instance of ThreadAbortException is thrown
try
{
Response.Redirect(url);
}
catch (ThreadAbortException ex)
{
//....
}
The line of code that follows Response.Redirect is not executed.
There is an overload method of Response.Redirect() without calling Response.End():
Response.Redirect(string url, bool endResponse);
In this overload the second parameter tells the system whether to make the internal call to Response.End() or not. When this parameter is false the client is sent the redirect url, but the internal call to Response.End is skipped. This completely avoids the code that would throw the exception, but the code that follows Response.Redirect is executed and the cost is that this thread doesn't stop executing the Application events!