C#"最终"阻止总是执行吗?

Rya*_*yer 68 c# try-catch

可能重复:
如果我在Try块中返回一个值,是否会触发Finally语句中的代码?

请考虑以下代码C#代码."finally"块是否执行?

public void DoesThisExecute() {
   string ext = "xlsx";
   string message = string.Empty;
   try {
      switch (ext) {
         case "xls": message = "Great choice!"; break;
         case "csv": message = "Better choice!"; break;
         case "exe": message = "Do not try to break me!"; break;
         default:
            message = "You will not win!";
            return;
      }
   }
   catch (Exception) {
      // Handle an exception.
   }
   finally {
      MessageBox.Show(message);
   }
}
Run Code Online (Sandbox Code Playgroud)

哈,在我写完这篇文章之后,我意识到我本可以在Visual Studio中自己测试过.但是,请随时回答!

kem*_*002 82

不,不是的.如果应用程序仍在运行,它将始终执行(除了在FastFail异常,MSDN链接期间,如其他人所指出的那样).它将在退出块的try/catch部分时执行.

如果应用程序崩溃,它将不会执行:通过kill process命令等被杀死.这非常重要,因为如果你编写绝对期望它运行的代码,就像手动进行回滚一样,如果不是其他方面它会自动执行提交,您可以遇到应用程序在发生之前中止的情况.老实说,这是一个外部场景,但在这些情况下注意很重要.

  • @Remus:不,只要无限循环完成,`finally`就会被调用... (9认同)
  • 这还包括一些异常(无法捕获的三个.net异常),Application.FailFast或Power Outage(http://thedailywtf.com/Articles/My-Tales.aspx) (4认同)
  • @DOK退货声明有什么问题? (4认同)
  • "......如果应用程序仍在运行." 很棒的. (4认同)
  • [记住这一点很好 - 最终*不是绝对保证.](http://thedailywtf.com/Articles/My-Tales.aspx) (4认同)

msa*_*het 52

从MSDN C#规范try声明:

一的语句finally在控制离开块总是被执行try的语句.这是真实的,控制传送是否发生正常的执行结果,作为执行的结果break,continue,goto,或return语句,或作为关于传播异常出的结果try说明.

资源

有些情况下finally块不会执行:

  1. Environment.FailFast
  2. 无法捕获的异常类型
  3. 电源(检测)失败

  • 我认为 finally 块中的代码会向 CPU 发出信号,指示 PSU 将存储在备用电容器中的最后一位电子直接路由到运行最终代码的核心,以防万一发生电源故障(给定 CLR 感知)当然是电源)。 (2认同)

Dir*_*mar 34

finally总是会被执行并不完全正确.见这个答案Haacked:

两种可能性:

  • StackOverflowException
  • ExecutingEngineException

当存在StackOverflowException时,不会执行finally块,因为堆栈上没有空间来执行任何更多的代码.当存在ExecutingEngineException时,它也不会被调用,这是非常罕见的.

实际上,对于任何类型的异步异常的(例如StackOverflowException,OutOfMemoryException,ThreadAbortException)一个的执行finally块不被保证.

但是,这些异常是您通常无法恢复的异常,并且在大多数情况下,您的进程无论如何都会退出.

事实上,至少还有一个案例finally没有像Brian Rasmussen在一个现在删除的问题中所描述的那样执行:

我知道的另一种情况是终结器抛出异常.在这种情况下,该过程也会立即终止,因此保证不适用.

下面的代码说明了这个问题

static void Main(string[] args) {
   try {
      DisposableType d = new DisposableType();
      d.Dispose();
      d = null;
      GC.Collect();
      GC.WaitForPendingFinalizers();
   } catch {
      Console.WriteLine("catch");
   } finally {
      Console.WriteLine("finally");
   }
}

public class DisposableType : IDisposable {
   public void Dispose() {
   }

   ~DisposableType() {
      throw new NotImplementedException();
   }
}
Run Code Online (Sandbox Code Playgroud)

一个可靠的try/catch/finally必须使用Constrained Execution Regions(CER).MSDN提供了一个示例:

[StructLayout(LayoutKind.Sequential)]
struct MyStruct
{
    public IntPtr m_outputHandle;
}

sealed class MySafeHandle : SafeHandle
{
    // Called by P/Invoke when returning SafeHandles
    public MySafeHandle()
        : base(IntPtr.Zero, true)
    {
    }

    public MySafeHandle AllocateHandle()
    {
        // Allocate SafeHandle first to avoid failure later.
        MySafeHandle sh = new MySafeHandle();

        RuntimeHelpers.PrepareConstrainedRegions();
        try { }
        finally
        {
            MyStruct myStruct = new MyStruct();
            NativeAllocateHandle(ref myStruct);
            sh.SetHandle(myStruct.m_outputHandle);
        }

        return sh;
    }
}
Run Code Online (Sandbox Code Playgroud)

以下文章是一个很好的信息来源:

可靠性最佳实践


Ian*_*obs 6

是的它确实:-) http://msdn.microsoft.com/en-us/library/zwc8s4fz.aspx

  • 不,它没有.http://thedailywtf.com/Articles/My-Tales.aspx (48认同)
  • @IvanZlatanov答案在问题的上下文中是正确的,其中OP显然想要知道即使在返回语句之后最终是否会执行,但是你确实存在最终不会执行的情况. (7认同)
  • 如果你放置"Process.GetCurrentProcess().Kill();" 或"Environment.FailFast("failfast");" 在try块中,finally块将不会执行.一些未发布的资源或非回滚事务可能会导致问题. (3认同)
  • @MikeNakis我试过了,并显示了最后的消息.我使用的是.NET 4.5.1 (2认同)

Len*_*rri 5

来自 MSDN try-finally(C# 参考)

finally 块对于清理在 try 块中分配的任何资源以及运行任何即使出现异常也必须执行的代码非常有用。不管 try 块如何退出,控制总是传递给 finally 块


归档时间:

查看次数:

75189 次

最近记录:

7 年,5 月 前