首页 > 解决方案 > 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.Threadis

我不明白为什么这些操作没有排队。

请记住,我处于单元测试上下文中,没有控件,因此我无法直接调用调度程序并为其设置计时器

添加一个以某种方式告诉 Dispatcher 使用其任务的静态类没有效果

更改为BeginInvoke并不能解决问题。

标签: c#wpfdispatcher

解决方案


假设在应用程序的 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;
}

推荐阅读