如何处理主应用引用的子应用关闭时的异常问题?
解决方案
针对你的场景,核心要区分App2作为独立应用运行和被App1引用作为子窗口运行两种情况,分别处理关闭逻辑:
1. 移除全局终止进程的代码
首先,把App2窗口Closing事件里的Environment.Exit(0)和无差别的Application.Current.Shutdown()都删掉——前者会直接终止整个进程(导致App1也被关掉),后者会关闭当前上下文的Application(如果是App1的上下文,就会关掉App1)。
2. 区分运行上下文处理关闭逻辑
在App2的MainWindow中,通过判断当前Application的归属,决定是否需要终止应用:
private void MainWindow_Closing(object sender, CancelEventArgs e) { // 先执行你的关闭前业务逻辑(比如保存数据、提示确认等) // ... // 判断当前是否是App2自己的Application实例(即独立运行) bool isStandalone = Application.Current is App2.App; if (isStandalone) { // 独立运行时,关闭窗口后终止整个应用 Application.Current.Shutdown(); } // 非独立运行(被App1引用)时,只关闭当前窗口,不影响App1 // 执行基类的关闭逻辑 base.OnClosing(e); }
3. 确保App2独立运行时能正常退出
如果单独启动App2后关闭窗口,进程仍在运行,大概率是以下两种情况:
- ShutdownMode设置错误:检查App2的
App.xaml或App.xaml.cs,确保ShutdownMode是默认的OnLastWindowClose(最后一个窗口关闭时自动终止应用)。如果是通过代码启动窗口,可手动设置:public partial class App : Application { protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); // 确保关闭最后一个窗口时自动退出应用 this.ShutdownMode = ShutdownMode.OnLastWindowClose; MainWindow.Instance.Show(); } } - 存在后台线程未终止:如果App2有后台线程(比如定时器、异步任务),且线程的
IsBackground属性设为false,那么即使窗口关闭,线程会继续运行导致进程无法退出。需要在窗口关闭时主动终止这些线程:private void MainWindow_Closed(object sender, EventArgs e) { // 终止后台线程、释放资源 // 比如:_backgroundThread?.Abort(); 或者通过CancellationToken取消任务 }
4. 优化单例窗口的逻辑
你的单例窗口实现没问题,为了更严谨可以用双重检查锁定优化线程安全性:
private static readonly object _lockObj = new object(); public static MainWindow Instance { get { lock (_lockObj) { if (AppWindow == null) { AppWindow = new MainWindow(); AppWindow.InitializeComponent(); AppWindow.Closed += (x, y) => { AppWindow = null; }; } return AppWindow; } } }
这样修改后,就能实现:
- 从App1打开App2窗口,关闭App2时仅关闭窗口,App1保持运行;
- 单独启动App2,关闭窗口后进程正常退出。
内容的提问来源于stack exchange,提问作者Steven
相关产品推荐
相关产品推荐

