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

WPF使用Prism6时Shell关闭前如何正确调用所有相关ViewModel的Dispose释放资源

Prism 6 WPF 应用Shell关闭前释放多模块资源解决方案

你遇到的PubSub事件无法触发的问题,90%以上的场景是因为订阅端没有持有强引用,或者发布/订阅两端使用的不是同一个IEventAggregator实例,以下是两种可直接落地的解决方案,尤其适配你的SQLTableDependency多模块监听场景:

方案1:修复PubSub事件通知逻辑(适合已有PubSub架构的项目)

注意:必须确保发布和订阅用的是同一个IEventAggregator实例,所有实例都从DI容器解析,不要手动new,这是事件触发失败的最常见原因。

  • 第一步:定义全局关闭事件
    public class ApplicationShutdownEvent : PubSubEvent { }
    
  • 第二步:ViewModel端正确订阅,保留订阅引用防止被GC回收
    public class YourModuleViewModel : BindableBase, IDisposable
    {
        private readonly SubscriptionToken _shutdownSubToken;
        private SqlTableDependency<YourTable> _sqlDependency;
    
        public YourModuleViewModel(IEventAggregator eventAggregator)
        {
            // 订阅时保留token,瞬态ViewModel需设置keepSubscriberReferenceAlive为true
            _shutdownSubToken = eventAggregator.GetEvent<ApplicationShutdownEvent>()
                .Subscribe(OnShutdown, keepSubscriberReferenceAlive: true);
            
            // 你的SQLTableDependency初始化逻辑
            _sqlDependency = new SqlTableDependency<YourTable>("你的连接串");
            _sqlDependency.Start();
        }
    
        private void OnShutdown()
        {
            Dispose();
        }
    
        public void Dispose()
        {
            _sqlDependency?.Stop();
            _sqlDependency?.Dispose();
            _shutdownSubToken?.Dispose();
        }
    }
    
  • 第三步:Shell关闭事件中正确发布事件
    public partial class Shell : Window
    {
        public Shell()
        {
            InitializeComponent();
            Closing += OnShellClosing;
        }
    
        private void OnShellClosing(object sender, CancelEventArgs e)
        {
            // 从全局容器解析IEventAggregator,不要用局部实例
            var eventAggregator = PrismApplicationBase.Current.Container.Resolve<IEventAggregator>();
            eventAggregator.GetEvent<ApplicationShutdownEvent>().Publish();
            
            // 等待异步释放操作完成,避免进程提前退出导致资源未释放
            Task.Delay(300).Wait();
        }
    }
    

方案2:全局资源托管(更推荐,完全规避PubSub失效问题)

适合多模块动态注册资源的场景,不用依赖事件通信,稳定性更高:

  • 第一步:定义全局资源托管服务
    public interface IAppResourceManager
    {
        void RegisterDisposable(IDisposable resource);
        void DisposeAll();
    }
    
    public class AppResourceManager : IAppResourceManager
    {
        private readonly List<IDisposable> _resources = new List<IDisposable>();
        private readonly object _lockObj = new object();
    
        public void RegisterDisposable(IDisposable resource)
        {
            lock (_lockObj)
            {
                if (!_resources.Contains(resource)) 
                    _resources.Add(resource);
            }
        }
    
        public void DisposeAll()
        {
            lock (_lockObj)
            {
                // 倒序释放避免依赖问题
                foreach (var res in _resources.AsEnumerable().Reverse())
                {
                    try { res.Dispose(); }
                    catch { /* 按需记录释放异常 */ }
                }
                _resources.Clear();
            }
        }
    }
    
  • 第二步:在App启动时将服务注册为单例
    protected override void RegisterTypes(IContainerRegistry containerRegistry)
    {
        containerRegistry.RegisterSingleton<IAppResourceManager, AppResourceManager>();
        // 你的其他注册逻辑
    }
    
  • 第三步:各模块初始化SQLTableDependency时注册资源
    // 模块初始化类或者对应ViewModel的构造函数中
    public YourModule(IAppResourceManager resManager)
    {
        var sqlDependency = new SqlTableDependency<YourTable>("你的连接串");
        sqlDependency.Start();
        // 注册到全局托管,不需要自己维护释放逻辑
        resManager.RegisterDisposable(sqlDependency);
    }
    
  • 第四步:Shell关闭时统一释放所有资源
    private void OnShellClosing(object sender, CancelEventArgs e)
    {
        var resManager = PrismApplicationBase.Current.Container.Resolve<IAppResourceManager>();
        resManager.DisposeAll();
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.16 03:27:03