You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Core 3.1 WPF应用Win10家庭版运行数天无异常自动关闭如何解决?

异常捕获机制遗漏点

你当前配置的两个全局异常事件存在覆盖盲区,是未捕获到异常的核心原因:

  • 未注册TaskScheduler.UnobservedTaskException事件:后台异步任务、async/await方法抛出的未捕获异常不会被现有两个事件捕获,.NET Core 3.1运行时遇到这类未处理异常会直接终止进程
  • 未覆盖非托管代码异常:调用C/C++动态库、COM组件等非托管代码抛出的结构化异常(SEH),默认不会被托管异常处理逻辑捕获,会直接导致进程闪退
  • 未覆盖WPF渲染线程异常:WPF独立渲染线程抛出的异常,部分场景不会触发UI调度线程的异常事件,直接触发进程退出

常见的2-3天周期性退出原因

这类长时间运行后才出现的退出,绝大多数是资源累积泄漏触发阈值导致:

  • GDI对象/用户对象泄漏:WPF程序如果高频创建画笔、字体、位图等GDI资源未释放,或者Image控件高频刷新未清理缓存,Win10家庭版单进程GDI对象上限为10000,触达上限会直接闪退
  • 内存泄漏:事件未取消订阅、静态集合持续新增元素未清理、非托管资源未释放等问题累积数天后触发OOM,系统直接杀掉进程
  • 系统层面触发终止:Windows自动更新前强制杀进程、杀毒软件误判异常行为终止进程、系统休眠/唤醒后进程上下文异常

排查解决步骤

1. 补全全局异常捕获

在原有异常注册逻辑基础上补充遗漏的事件:

using System.Runtime.ExceptionServices;
using System.Security;

void App_Startup(object sender, StartupEventArgs e) 
{
    // 原有逻辑保留
    Application.Current.DispatcherUnhandledException += Current_DispatcherUnhandledException;
    AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
    // 新增未观察到的异步任务异常捕获
    TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
    // 新增进程退出日志记录
    AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit;
}

[HandleProcessCorruptedStateExceptions, SecurityCritical]
private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
{
    Log.Logger.Fatal(e.Exception, "TaskScheduler未观察到的异步异常");
    e.SetObserved(); // 标记异常已处理,避免进程直接退出
    MessageBox.Show($"异步任务异常:{e.Exception.InnerException?.Message}", "异常提示", MessageBoxButton.OK, MessageBoxImage.Error);
}

private void CurrentDomain_ProcessExit(object sender, EventArgs e)
{
    Log.Logger.Fatal("进程触发退出,退出时间:{time}", DateTime.Now);
}

如果程序调用了非托管代码,需要在对应异常处理方法上添加[HandleProcessCorruptedStateExceptions]和[SecurityCritical]特性,才能捕获损坏状态的非托管异常。

2. 排查资源泄漏问题

  • 打开任务管理器「详细信息」 tab,右键表头勾选「GDI对象」「用户对象」「句柄数」「提交大小」,持续观测程序对应指标的增长趋势:如果GDI对象持续上涨到接近10000,就是GDI泄漏;如果内存持续无上限上涨就是内存泄漏
  • 用PerfView、dotMemory工具抓取进程快照,定位泄漏的资源类型和对应的业务代码

3. 排查系统层面日志

打开Windows事件查看器,进入「Windows日志>应用程序」,筛选对应退出时间点的错误日志:

  • 来源为.NET Runtime的日志会记录托管异常的详细堆栈
  • 来源为Application Error的日志会记录进程退出的错误码,比如0xC0000005是非托管访问违例、0xC00000FD是栈溢出
  • 同时查看系统日志的更新记录、电源日志,排除系统重启、休眠的影响

4. 兜底兼容方案

对于长时间无人值守运行的程序,可以额外开发一个极简的守护进程,定时检测主程序进程是否存在,一旦退出自动拉起,同时记录退出状态方便后续排查。


内容的提问来源于stack exchange,提问作者Chu Artistmonkey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 11:15:03