Why is the code in the finally block not executing?

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?

+8
multithreading c # try-catch-finally
source share
2 answers

Your code runs in the background thread. When you set AutoResetEvent , your single front thread ends (as you reach the end of the Main method), and the process is immediately reset.

Actually, I think your finally block will start executing, but since the first thing you do is sleep for two seconds, the process ends before it reaches your WriteLine call.

If your Main method still worked or some other foreground thread supported the process, you will see that your finally block is completed as usual. Actually, this is not the question “finally, on other threads” - this is the question “the process remains alive as long as there are front threads”.

+17
source share

You can prevent the main method from running until it is finally executed. There are many possible approaches.

  • You can use synchronization to achieve this. For example, using ResetEvent, similar to what you are already doing, or create a stream explicitly and join it.

  • At the end of the Main method, you could just sleep or readline:

     h.WaitOne(); Console.ReadLine(); 

Then the user can control when the program exits.

  • You can use a nephonic thread instead of a thread from a thread pool. Then the program will not exit until the thread terminates. This is probably the best and easiest option if you want your program to not end before the thread ends.
+4
source share

All Articles