It seems that finally the block is not executed if it is different from the main thread execution code. Is it possible to force execution in this case?
Environment: VS 2010, .Net Framework 4.0.3
class Program { static void Main(string[] args) { var h = new AutoResetEvent(false); ThreadPool.QueueUserWorkItem( obj => TestProc(h)); h.WaitOne(); } private static void TestProc(EventWaitHandle h) { try { Trace.WriteLine("Try"); h.Set(); } catch(Exception) { Trace.WriteLine("Catch"); } finally { Thread.Sleep(2000); Trace.WriteLine("Finally"); } } }
Update:
I found mentions and explanations in this case on MSDN:
Class ThreadAbortException http://msdn.microsoft.com/en-us/library/system.threading.threadabortexception.aspx
When calling the Abort method to kill a thread, Common Language run throws a ThreadAbortException. ThreadAbortException is a special exception that can be caught, but it will be automatically raised again at the end of the catch block. when this exception is raised, runtime executes all finally blocks until the end of the stream . Since a thread can perform unlimited computation in finally blocks or call Thread.ResetAbort to cancel an interrupt, it does not guarantee that the thread will never end . If you want to wait until the terminated thread ends, you can call Thread.Join. A join is a blocking call that does not return until the thread actually terminates.
Note:
When the common language common language runtime (CLR) stops the background thread after all the foreground threads in the managed executable have run out, do not use Thread.Abort. Therefore, you cannot use a ThreadAbortException to detect when background threads are interrupted by the CLR.
Key topics and background topics http://msdn.microsoft.com/en-us/library/h339syd0.aspx
When the runtime stops the background thread because the process is terminating, an exception is not thrown in the thread. However, when threads stop because the AppDomain.Unload method unloads the application domain, a ThreadAbortException is thrown both in the background and in the front thread.
So, why at the end of the application does the CLR not use the AppDomain.Unload method to unload the application domain before the completion (termination) of the main process? Because http://msdn.microsoft.com/en-us/library/system.appdomain.unload.aspx :
When a thread calls Unload, the target domain is marked for unloading. A special thread tries to unload the domain, and all flows to the domain are interrupted. If the thread does not interrupt, for example because it is executing unmanaged code, or because it is finally executing a block, then after some time the CannotUnloadAppDomainException is thrown into the thread that is initially called by Unload. If a thread that cannot be interrupted eventually ends, the target domain is not unloaded. Thus, in the .NET Framework, a version 2.0 domain does not guarantee unloading , since it may not be possible to terminate threads.
Conclusion: In some cases, I need to consider whether my code will execute in the background or front thread? Is it possible that my code will not be completed before the entire main thread of the application ends?