如何确保在崩溃 c# 时保存应用程序状态

Posted

技术标签:

【中文标题】如何确保在崩溃 c# 时保存应用程序状态【英文标题】:How to ensure saving of application state on crash c# 【发布时间】:2012-03-08 19:17:09 【问题描述】:

我对 c# 编程很陌生,所以请记住:

我有一个内存数据对象,其中包含在(如果)我的应用程序崩溃或关闭时需要保存信息的数据。有没有办法确定或可靠地做到这一点?

我一直在看析构函数

~MyObjectName()

终结器和 Dispose(),

但据我了解,这些都不能可靠地满足我的要求?

目前我正在使用析构函数,当我关闭程序时它可以工作,但这并不意味着它会在崩溃时工作,或者总是。

我也应该关注事件吗?

【问题讨论】:

如果你的应用程序崩溃了,那么你不能保证你想要保存的对象的状态是有效的。确保您的应用程序不会崩溃不是更容易吗? 应用程序很大。我只想保存某些状态变量/内存表等。我继承了这个项目,所以虽然这将是我正常选择的操作,但在这种情况下,无法调试并确保它不会崩溃。 【参考方案1】:

当进程(任何进程,而不仅仅是 .Net 进程)终止时,您可以使用 100% 可靠的机制来保存数据(或为此做任何其他事情) - 大多数情况下可以使用任务管理器中的“结束进程”选项随时终止进程,当这种情况发生时,进程会立即被终止。作为一个更极端的例子,可以将电源线从机器背面拉出。

如果不是 100% 需要此数据对象是最新的并在进程被终止后保存,那么 AppDomain.UnhandledException Event 可能就足够了。

如果绝对 100% 需要这种情况,那么您需要在流程运行时不断保存此信息 - 绝对不能保证您以后有机会这样做。这就是数据库的操作方式,直到某些更改记录以某种格式(例如事务日志)记录到磁盘后,才会返回事务。这就是 ACID 中 D 的含义。

【讨论】:

您提出了非常好的和有效的观点,但 UnhandledException 事件更像是我正在寻找的类型。当我说关闭或崩溃时,我的意思是软件故障(异常)或用户终止应用程序。不幸的是,像在数据库中那样一直写入磁盘的性能太慢了。我实际上想要做的只是尽可能多地保存信息,以减少应用程序重新启动时的负载。 @Vort3x 如果数据完整性未处于状态,我将只使用未处理的异常事件。 是的,在我看来这是最好的解决方案。可能我要保存的主要数据是已接收到的已排序的 UDP 数据报的缓存。如果程序崩溃,我必须从源重新请求这些消息,这会停止处理数据包,但如果我至少可以保存当前现金中的内容,我可以减少重新请求的数量,这意味着更短的停机时间。【参考方案2】:

我相信您正在寻找捕获未处理的异常?像这样:

static void Main()

  Application.EnableVisualStyles();
  Application.SetCompatibleTextRenderingDefault(false);

  Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);
  AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

  Application.Run(new Form1());


static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)

  MessageBox.Show(e.Exception.Message, "Unhandled Thread Exception");
  // here you can log the exception ...


static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)

  MessageBox.Show((e.ExceptionObject as Exception).Message, "Unhandled UI Exception");
  // here you can log the exception ...

此示例展示了如何管理所有尚未处理的异常 捕获在 try-catch 部分(在 Windows 窗体应用程序中)。

UnhandledException 事件处理从 主 UI 线程。 ThreadException 事件处理未捕获的 非 UI 线程抛出的异常。

【讨论】:

【参考方案3】:

您可以使用 windbg 实现此目的。

    在windbg 的zwterminateprocess 方法中保留breakpoint。当您的应用程序退出时,将调用此方法。 到达断点时,使用 !dumpheap -type MyObjectName 获取对象的地址 使用 !dumpobject "address of MyObjectName" 了解对象内部的值

【讨论】:

以上是关于如何确保在崩溃 c# 时保存应用程序状态的主要内容,如果未能解决你的问题,请参考以下文章

Android 片段不保存状态,在旋转/屏幕锁定/返回时崩溃

在 C# 中执行邮件合并时 LibreOffice 崩溃

崩溃CGDataProviderCreateWithCopyOfData:vm_copy失败:状态1

保存/恢复android webview的状态

应用退出时如何确保 NSUserDefaults 设置保存到磁盘?

如何确保 CodeDeploy 在清除缓存时保持所有自动扩展组实例处于维护状态?