GOTCHA #55 Abort() takes time to clean upAs you saw in Gotcha #52, "ThreadAbortExceptiona hot potato," when you abort a THRead, the CLR throws a ThreadAbortException on it. The thread can do whatever cleanup it needs to by handling the exception. The CLR then executes all the finally blocks in the thread's call stack before actually terminating it. So there might be a delay between the time you call Abort() and the time the thread quits. This is illustrated in Example 7-7. Example 7-7. Delay during Abort
using System; using System.Threading; namespace AbortAndJoin { class Test { private static void Worker() { Console.WriteLine("Worker started"); try { Thread.Sleep(5000); } finally { Console.WriteLine("Worker enters finally {0}", DateTime.Now.ToLongTimeString()); Thread.Sleep(10000); // Simulates some cleanup activity Console.WriteLine("Cleanup done in Worker {0}", DateTime.Now.ToLongTimeString()); } } [STAThread] static void Main(string[] args) { Thread workerThread = new Thread(new ThreadStart(Worker)); workerThread.IsBackground = true; workerThread.Start(); Thread.Sleep(1000); Console.WriteLine("Aborting thread {0}", DateTime.Now.ToLongTimeString()); workerThread.Abort(); workerThread.Join(); Console.WriteLine("Thread has aborted {0}", DateTime.Now.ToLongTimeString()); } } }
Imports System.Threading Module Test Private Sub Worker() Console.WriteLine("Worker started") Try Thread.Sleep(5000) Finally Console.WriteLine("Worker enters finally {0}", _ DateTime.Now.ToLongTimeString()) Thread.Sleep(10000) ' Simulates some cleanup activity Console.WriteLine("Cleanup done in Worker {0}", _ DateTime.Now.ToLongTimeString()) End Try End Sub Public Sub Main() Dim workerThread As New Thread(AddressOf Worker) workerThread.IsBackground = True workerThread.Start() Thread.Sleep(1000) Console.WriteLine("Aborting thread {0}", _ DateTime.Now.ToLongTimeString()) workerThread.Abort() workerThread.Join() Console.WriteLine("Thread has aborted {0}", _ DateTime.Now.ToLongTimeString()) End Sub End Module In this example, the Worker() method's finally block introduces a delay to simulate some activity. Main() first starts a thread to run the Worker() method. After a delay, it invokes Abort() on that thread. Then it calls Join() to wait for cleanup and completion. The output is shown in Figure 7-8. Figure 7-8. Output from Example 7-7![]() If your application requires you to Abort() a thread and perform some operation after that thread has quit, you should call Join() on the thread after calling Abort(). This waits for the thread to clean up properly and exit gracefully before you continue processing.
|