c# - WPF 调度程序在运行 UI 测试时从不执行操作
问题描述
我有一个内部使用 a来异步Dispatcher
更新的ViewModel。ObservableCollection
我想为该 ViewModel 编写一个单元测试,包括使用 Dispatcher 的方法。
我已经使用IDispatcher
在运行时注入的自定义来抽象调度程序。
这是IDispatcher
我在应用程序以正常模式运行时使用的实现
public class WPFDispatcher : IDispatcher
{
public void Invoke(Action action)
{
System.Windows.Application.Current.Dispatcher.Invoke(action);
}
}
ViewModel 使用IDispatcher
类似的东西
public async Task RefreshControls()
{
Parent.IsSoftBusy = true;
if (ControlsList == null)
ControlsList = new ObservableCollection<DataprepControl>();
await Task.Run(() =>
{
var updatedControls = _getControls();
Dispatcher.Invoke(() => _handleUpdatedControl(updatedControls));
});
Parent.IsSoftBusy = false;
}
从单元测试(Visual Studio 单元测试框架)切换到执行时,System.Windows.Application` 可能为空,因此我在单元测试启动时手动实例化它
new System.Windows.Application();
这样做时,Actions
传递给永远不会Invoke
被执行,它们会无限期地挂起。
如果我在调用中添加断点Invoke
,我会看到Dispatcher.Thread
is
- 在 STA 模式下(因此它可以处理 GUI 更新)
- 还活着 (
IsAlive == true
) - 处于状态
Background | WaitSleepJoin
(我不知道这意味着什么,但它可能有用)
我不明白为什么这些操作没有排队。
请记住,我处于单元测试上下文中,没有控件,因此我无法直接调用调度程序并为其设置计时器
添加一个以某种方式告诉 Dispatcher 使用其任务的静态类没有效果
更改为BeginInvoke
并不能解决问题。
解决方案
假设在应用程序的 UI 线程中调用视图模型方法,以下代码修改应该消除使用 Dispatcher 的需要:
public async Task RefreshControls()
{
Parent.IsSoftBusy = true;
if (ControlsList == null)
{
ControlsList = new ObservableCollection<DataprepControl>();
}
var updatedControls = await Task.Run(() => _getControls());
_handleUpdatedControl(updatedControls);
Parent.IsSoftBusy = false;
}
推荐阅读
- sql - 如何使用 PostgreSQL 中的变量创建具有内部连接的视图?
- javascript - 包括在空格后找不到字符
- java - Java使用ajax创建和下载文件不起作用
- node.js - 如何使用 npm 安装 node-win-shortcut
- node.js - node/express 中的“/register”和“register”路由是否相同?
- vb.net - 使用 async/await 从另一个任务更新 gui 时出现问题
- .net-core - 跳过 .NET Core 控制台应用程序的依赖项检查
- php - 对于将数据上传到服务器上的 PHP 脚本的私有内部公司应用程序,我应该有哪些潜在的安全问题?
- javascript - 无法获得图表 js 中显示的预期图例
- python - 从边界框计算轨迹