.NET threading: how can I capture an abort on an unstarted thread?
- by Groxx
I have a chunk of threads I wish to run in order, on an ASP site running .NET 2.0 with Visual Studio 2008 (no idea how much all that matters, but there it is), and they may have aborted-clean-up code which should be run regardless of how far through their task they are. So I make a thread like this:
Thread t = new Thread(delegate() {
try {
/* do things */
System.Diagnostics.Debug.WriteLine("try");
}
catch (ThreadAbortException) {
/* cleanup */
System.Diagnostics.Debug.WriteLine("catch");
}
});
Now, if I wish to abort the set of threads part way through, the cleanup may still be desirable later on down the line. Looking through MSDN implies you can .Abort() a thread that has not started, and then .Start() it, at which point it will receive the exception and perform normally. Or you can .Join() the aborted thread to wait for it to finish aborting. Presumably you can combine them.
http://msdn.microsoft.com/en-us/library/ty8d3wta(v=VS.80).aspx
To wait until a thread has aborted, you can call the Join method on the thread after calling the Abort method, but there is no guarantee the wait will end.
If Abort is called on a thread that has not been started, the thread will abort when Start is called. If Abort is called on a thread that is blocked or is sleeping, the thread is interrupted and then aborted.
Now, when I debug and step through this code:
t.Abort(); // ThreadState == Unstarted | AbortRequested
t.Start(); // throws ThreadStartException: "Thread failed to start."
// so I comment it out, and
t.Join(); // throws ThreadStateException: "Thread has not been started."
At no point do I see any output, nor do any breakpoints on either the try or catch block get reached.
Oddly, ThreadStartException is not listed as a possible throw of .Start(), from here: http://msdn.microsoft.com/en-us/library/a9fyxz7d(v=VS.80).aspx (or any other version)
I understand this could be avoided by having a start parameter, which states if the thread should jump to cleanup code, and foregoing the Abort call (which is probably what I'll do). And I could .Start() the thread, and then .Abort() it. But as an indeterminate amount of time may pass between .Start and .Abort, I'm considering it unreliable, and the documentation seems to say my original method should work.
Am I missing something? Is the documentation wrong?
edit: ow. And you can't call .Start(param) on a non-parameterized Thread(Start). Is there a way to find out if a thread is parameterized or not, aside from trial and error? I see a private m_Delegate, but nothing public...