-->

Why is a finally block *sometimes* not executed on

2019-03-31 04:13发布

问题:

UPDATE: I don't think this question is a duplicate of Can ThreadAbortException skip finally? because (1) I'm not creating another thread, so there's no possibility of a race condition, and (2) this behavior only occurs if the finally block contains an await, which that other question doesn't mention.


Consider this console program:

class Program
{
    static void Main()
    {
        try { T().GetAwaiter().GetResult(); }
        catch (ThreadAbortException) { Thread.ResetAbort(); }
        catch { }
    }

    static async Task Abort()
    {
        //await Task.Delay(1); // A
        Thread.CurrentThread.Abort(); // B
    }

    static async Task T()
    {
        try
        {
            await Abort();
        }
        catch
        {
            Console.WriteLine("catch");
            throw;
        }
        finally
        {
            Console.WriteLine("finally");
            await Task.Yield(); // C
        }
    }
}

When I compile this in Visual Studio 2015, the output is

catch

But if I make any one of these changes...

  1. Uncomment line A (and delete the call to Thread.ResetAbort() in Main—another oddity)
  2. Change line B to throw new Exception();
  3. Delete line C

then the output is

catch
finally

Is this behavior a bug, or is it by design (and documented somewhere)?

NOTE: In my actual scenario (an ASP.NET app), the ThreadAbortException is thrown by HttpResponse.Redirect, and I'm performing async I/O in the finally block.