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

Caliburn Micro:确保应用关闭前所有OnDeactivate均被调用及相关问题

问题解决:确保所有ViewModel的OnDeactivate被调用 + Caliburn规范的TryClose实现

一、为什么只有部分ViewModel的OnDeactivate被触发?

你的核心问题在于过早调用了Application.Current.Shutdown()或Environment.Exit(0)——这两个方法会直接终止整个应用进程,跳过Caliburn.Micro的ViewModel生命周期流程,导致还没来得及遍历所有子ViewModel并触发它们的OnDeactivate方法就关机了。之前加的Sleep没用,是因为它在后台线程执行,主线程已经触发了关机命令,进程直接终止了。

二、如何确保所有ViewModel的OnDeactivate被调用?

你需要让Caliburn完成完整的生命周期清理后再考虑关机,而不是强制终止。修改你的TryClose方法,先手动触发所有子ViewModel的Deactivate逻辑,再执行基类的关闭流程:

public override async void TryClose(bool? dialogResult = default(bool?))
{
    // 1. 遍历所有子ViewModel,手动触发Deactivate(确保close参数为true)
    // 用ToList()避免遍历过程中集合发生变化
    foreach (var screen in Items.ToList())
    {
        // 调用Caliburn的Deactivate方法,确保触发OnDeactivate
        // 如果是旧版Caliburn(无异步方法),可以用screen.OnDeactivate(true),但要确保在UI线程
        await screen.DeactivateAsync(true);
    }

    // 2. 执行你的自定义清理逻辑
    // some dispose logic here

    // 3. 调用基类的TryClose,让Conductor完成自身的关闭流程
    base.TryClose(dialogResult);

    // 4. 显示关闭提示(这部分可以保留,但不需要依赖它来延迟关机)
    await Task.Run(() => {
        using (StartBusy(ViewModelBusyReason.Closing))
        {
            Thread.Sleep(2000);
        }
    });

    // 5. 通常不需要手动调用Shutdown!基类TryClose会处理应用关闭,除非有特殊强制需求
    // Application.Current.Shutdown();
    // Environment.Exit(0); // 绝对不推荐,会跳过所有清理
}

三、Caliburn规范的ShellViewModel TryClose实现

对于继承自Conductor<Screen>.Collection.OneActive的ShellViewModel,基类的TryClose已经内置了子ViewModel的关闭逻辑:

  1. 基类会自动遍历所有子ViewModel,触发它们的OnDeactivate(当close参数为true时)。
  2. 当ShellViewModel自身关闭后,Caliburn会自动关联到WPF应用的关闭事件,不需要你手动调用Application.Current.Shutdown()。
  3. 规范的实现应该是:
    • 先执行Shell自身的清理逻辑。
    • 调用基类的TryClose,让Caliburn的生命周期流程自然完成。
    • 除非有特殊场景(比如强制终止无响应的进程),否则绝对不要用Environment.Exit(0),它会跳过所有.NET的资源释放流程。

额外提示

如果你的子ViewModel有异步清理逻辑,建议使用Caliburn.Micro 3.0+提供的异步生命周期方法DeactivateAsync(而不是同步的OnDeactivate),这样可以确保异步清理完成后再继续关闭流程,避免资源泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:13:39