【发布时间】:2011-01-29 16:15:48
【问题描述】:
即使我的 C# 应用程序崩溃(删除临时文件等),我也想在执行结束时执行一些清理代码。在 C# 中可以做到这一点吗?
谢谢!
【问题讨论】:
-
非软件工程师所说的这个词是什么意思:任何导致应用程序崩溃的事件(任何线程中的未处理异常、除以 0、访问冲突、来自我的工作 DLL 的 C++ SEH等等)。
即使我的 C# 应用程序崩溃(删除临时文件等),我也想在执行结束时执行一些清理代码。在 C# 中可以做到这一点吗?
谢谢!
【问题讨论】:
这取决于您所说的“崩溃”。
如果您想处理任何可能导致应用程序崩溃的未处理异常,您可以将事件处理程序附加到 AppDomain.UnhandledException 事件,然后在事件处理程序中处理任何错误。
此外,在 .Net 4.0 中有一个 AppDomain.FirstChanceException 在发生异常时在执行任何 catch 块之前调用。
但是,可能会发生真正的崩溃(例如从终结器引发的异常),导致无法轻松处理的致命应用程序退出,但在大多数情况下,AppDomain.UnhandledException 事件可能就足够了。
【讨论】:
如果您的应用程序崩溃,那么尝试执行清理代码是不安全的,您不知道什么已损坏,直到您的应用程序真正退出,文件可能被锁定等。
所以我建议你把这个清理代码放在应用程序启动上。让您的应用程序在启动时查找临时文件等,然后再创建正常的临时文件,如果找到它们,则可以删除它们或尝试修复/重用它们。
为了方便这一点,您可以让您的应用程序写入它创建的临时文件的日志,并在它关闭时删除该日志文件成功。这样,当您在启动时找到日志文件时,您就知道上次运行是崩溃,您必须进行清理。
当然,如果您允许应用程序的多个实例同时运行,这会变得更加复杂,但在崩溃时清理内容也是如此。
【讨论】:
您可以订阅多个事件以获得异常通知。
此外,正如其他人所提到的,围绕单个入口点的 finally 块将针对主线程上的任何异常而被命中。
[我不建议尝试从这些处理程序中恢复您的应用程序。特别是在 AppDomain.UnhandledException 事件的情况下,您的应用程序已经退出,您应该让它关闭。仅将这些处理程序用于最后一分钟的清理或记录。]
【讨论】:
如果清理您的应用程序至关重要,您可以创建一个监控应用程序,该应用程序将是用户实际启动的内容。它将启动您的主应用程序,然后监视其进程句柄。如果您的主应用程序崩溃,它的进程句柄将发出信号,并且您的监控应用程序可以清理甚至重新启动主应用程序,如果您愿意。我通常将它与一个命名的互斥锁结合使用,该互斥锁用于向监控应用发出信号,表明主应用希望关闭,这样它就不会重新启动它。
【讨论】:
这取决于您所说的“崩溃”是什么意思。如果您的意思是未处理的异常,您可以为 Application.ThreadException 创建一个处理程序。如果崩溃是在托管代码之外引起的,那么您无能为力。
【讨论】:
这就是try {} finally {} 的用途。将您的所有代码包装在您的 main 方法中,应该这样做。
【讨论】: