WPF 多线程 UI:设计一个异步加载 UI 的容器
对于 WPF 程序,如果你有某一个 UI 控件非常复杂,很有可能会卡住主 UI,给用户软件很卡的感受。但如果此时能有一个加载动画,那么就不会感受到那么卡顿了。UI 的卡住不同于 IO 操作或者密集的 CPU 计算,WPF 中的 UI 卡顿时,我们几乎没有可以让 UI 响应的方式,因为 WPF 一个窗口只有一个 UI 线程。
No!WPF 一个窗口可以不止一个 UI 线程,本文将设计一个异步加载 UI 的容器,可以在主线程完全卡死的情况下显示一个加载动画。
本文是对我另一篇博客 WPF 同一窗口内的多线程 UI(VisualTarget) 的一项应用。阅读本文,你将得到一个 UI 控件 AsyncBox
,放入其中的控件即便卡住主线程,也依然会有一个加载动画缓解用户的焦虑情绪。
本文内容
- 异步加载的效果预览
- 使用我写的 WPF 异步加载控件 AsyncBox
- 现在,我们来实现这个异步加载 UI 的容器
- 附 AsyncBox 的源码
Annotations.cs
这些文件都是通用的异步类型。
第 5 个文件 AsyncBox
就是我们要实现的主要类型。
实现思路是建一个 PresentationSource
(类似于窗口的根 HwndSource
),这可以用来承载一个新的可视化树(Visual Tree)。这样,我们就能在一个窗口中显示两个可视化树了。
这两个可视化树通过 HostVisual
跨线程连接起来,于是我们能在一个窗口中得到两个不同线程的可视化树。
由于这两棵树不在同一个线程中,于是主线程即便卡死,也不影响后台用来播放加载动画的线程。