WPF类库外部调用时Dispatcher.BeginInvoke不触发且Application.Current为null
问题根因
- 从非WPF宿主程序通过独立STA线程拉起WPF窗口时,没有初始化WPF运行必需的
Application实例,WPF的Dispatcher调度、UI生命周期管理都依赖该实例,缺失时就会出现Application.Current = null、Dispatcher.BeginInvoke注册的委托不执行的问题。 - 原启动代码的事件绑定顺序错误:
ShowDialog()是阻塞调用,等窗口关闭后才会执行后续的Closed事件绑定逻辑,该事件永远不会触发,会导致Dispatcher无法正常退出,引发线程泄漏。 - 窗口内部跨线程调用
Dispatcher.BeginInvoke时没有明确指定UI线程所属的Dispatcher实例,跨线程场景下容易拿到错误的Dispatcher引用,导致调度失败。
修复代码
调整窗口启动线程逻辑
在STA线程入口处优先初始化Application实例,调整事件绑定顺序,补充线程配置:
Thread thre = new Thread(() => { // 初始化WPF Application实例,仅在不存在时创建 if (Application.Current == null) { new Application(); } mainwindow md = new mainwindow(); // 先注册关闭事件,再显示窗口 md.Closed += (s, e) => md.Dispatcher.InvokeShutdown(); md.ShowDialog(); Dispatcher.Run(); }); thre.SetApartmentState(ApartmentState.STA); thre.IsBackground = true; // 设为后台线程,避免宿主进程退出后线程残留 thre.Start();
修正窗口内部跨线程调用逻辑
跨线程更新UI时,明确指定当前窗口所属的Dispatcher,避免引用错误:
new Thread(() => { var result = getItemID("44"); // 显式调用窗口自身的Dispatcher调度UI逻辑 this.Dispatcher.BeginInvoke(new ThreadStart(() => { if (result == 0) { // 此处写result匹配后的业务逻辑 } })); }).Start();
注意:如果类库需要支持多次唤起WPF窗口,全局只需要初始化一次
Application实例即可,重复创建会抛出运行时异常。
内容的提问来源于stack exchange,提问作者Zakeer
相关产品推荐
相关产品推荐

