WPF Caliburn.Micro升级后PlatformProvider获取错误导致UI线程调用异常
Caliburn.Micro 3.2.0 升级到 4.0.173 跨ViewModel PlatformProvider 异常问题解决
问题表现
- ShellViewModel 中调用
PlatformProvider.Current可正常返回预期的XamlPlatformProvider - 通过 Frame 导航进入的子 ViewModel 中,
PlatformProvider.Current返回值为DefaultPlatformProvider,仅 ShellViewModel 不受影响
引发的报错
- 调用
Caliburn.Micro.Execute.OnUIThread执行UI组件创建逻辑时抛出异常:调用线程必须为STA,因为许多UI组件都有此要求 - 操作
BindableCollection时抛出异常:该类型的CollectionView不支持从不同于Dispatcher线程的线程更改其SourceCollection
临时验证方案
将所有涉及Caliburn.Micro平台相关调用的逻辑用 Application.Current.Dispatcher.Invoke 包裹后可正常执行,确认是Caliburn.Micro内部未正确绑定UI线程Dispatcher导致的问题。
适用场景
技术栈:C# + .NET Framework 4.8
排查前置:小型测试项目无法复现,替换Bootstrapper为最简版本后问题依旧存在。
根因定位
Caliburn.Micro 4.x 版本对 PlatformProvider.Current 的取值逻辑做了调整,不再默认使用全局单例,会优先读取当前视图的资源上下文里的Provider实例:
Frame导航时会创建独立的资源上下文,子页面未继承Shell层已经初始化的XamlPlatformProvider实例,导致子视图绑定的ViewModel读取到无Dispatcher绑定的默认DefaultPlatformProvider。
最终解决方案
任选以下一种方案即可:
- 在App.xaml中全局注册
XamlPlatformProvider,确保所有视图上下文都能读取到同一个实例:
<Application.Resources> <caliburn:XamlPlatformProvider x:Key="PlatformProvider" /> </Application.Resources>
- 在Bootstrapper的Configure方法中强制全局覆盖
PlatformProvider.Current的默认实例,优先级高于上下文读取:
protected override void Configure() { // 其他原有配置逻辑 PlatformProvider.Current = new XamlPlatformProvider(); }
- 若项目自定义了Frame导航逻辑,导航完成后手动将子Page的DataContext关联的ViewModel的PlatformProvider指向全局实例即可。
内容的提问来源于stack exchange,提问作者Emil Nyborg
相关产品推荐
相关产品推荐

