C# Time of finally execution

后端 未结 9 1619
情话喂你
情话喂你 2021-02-04 01:37

Take this code:

using System;

namespace OddThrow
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
              


        
相关标签:
9条回答
  • 2021-02-04 02:02

    To add more into the mix, consider this:

    using System;
    namespace OddThrow
    {
        class Program
        {
            static void Main()
            {
                AppDomain.CurrentDomain.UnhandledException +=
                    delegate(object sender, UnhandledExceptionEventArgs e)
                {
                    Console.Out.WriteLine("In AppDomain.UnhandledException");
                };
                try
                {
                    throw new Exception("Exception!");
                }
                catch
                {
                    Console.Error.WriteLine("In catch");
                    throw;
                }
                finally
                {
                    Console.Error.WriteLine("In finally");
                }
            }
        }
    }
    

    Which on my system (Norwegian) shows this:

    [C:\..] ConsoleApplication5.exe
    In catch
    In AppDomain.UnhandledException
    
    Ubehandlet unntak: System.Exception: Exception!
       ved OddThrow.Program.Main() i ..\Program.cs:linje 24
    In finally
    
    0 讨论(0)
  • 2021-02-04 02:04

    Although not completely expected, the program does behave as it should. A finally block is not expected to be run first, it is only expected to be run always.

    I adjusted your sample:

    public static void Main()
    {
        try
        {
            Console.WriteLine("Before throwing");
            throw new Exception("Exception!");
        }
        finally
        {
            Console.WriteLine("In finally");
            Console.ReadLine();
        }
    }
    

    In this case you will get the nasty unhandled exception dialog, but afterwards the console will output and wait for input, thus executing the finally, just not before windows itself catches the unhandled exception.

    0 讨论(0)
  • 2021-02-04 02:07

    A try/finally without a catch will use the default handler which does exactly what you see. I use it all the time, e.g., in cases where handling the exception would be covering an error but there's still some cleanup you want to do.

    Also remember that output to standard error and standard out are buffered.

    0 讨论(0)
  • 2021-02-04 02:08

    The output is actually from the default CLR exception handler. Exception Handlers occur before the finally block. After the finally block the CLR terminates because of the unhandled exception (it can't terminate before, as c# guarantees [1] that the finally clause is called).

    So I'd say it's just standard behaviour, exception handling occurs before finally.

    [1] guranteed during normal operation at least in absence of internal runtime errors or power outage

    0 讨论(0)
  • 2021-02-04 02:10

    The try-catch-finally blocks are working exactly as you expected if they are caught at some point. When I wrote a test program for this, and I use various nesting levels, the only case that it behaved in a way that matched what you described was when the exception was completely unhandled by code, and it bubbled out to the operating system.

    Each time I ran it, the OS was what created the error message. So the issue is not with C#, it is with the fact that an error that is unhandled by user code is no longer under the control of the application and therefore the runtime (I believe) cannot force an execution pattern on it.

    If you had created a windows form application, and wrote all your messages to a textbox (then immediately flushing them) instead of writing directly to the console, you would not have seen that error message at all, because it was inserted into the error console by the calling application and not by your own code.

    EDIT

    I'll try to highlight the key part of that. Unhandled exceptions are out of your control, and you cannot determine when their exception handler will be executed. If you catch the exception at some point in your application, then the finally blocks will be executed before the lower-in-the-stack catch block.

    0 讨论(0)
  • 2021-02-04 02:16

    The standard's statements about the order of execution are correct, and not inconsistent with what you are observing. The "Unhandled exception" message is allowed to appear at any point in the process, because it is just a message from the CLR, not actually an exception handler itself. The rules about order of execution only apply to code being executed inside the CLR, not to what the CLR itself does.

    What you've actually done is expose an implementation detail, which is that unhandled exceptions are recognised by looking at a stack of which try{} blocks we are inside, rather than by actually exploring all the way to the root. Exceptions may or may not be handled by looking at this stack, but unhandled exceptions are recognised this way.

    As you may be aware, if you put a top-level try{}catch{} in your main function, then you will see the behaviour you expect: each function's finally will be executed before checking the next frame up for a matching catch{}.

    0 讨论(0)
提交回复
热议问题