【发布时间】:2018-11-13 13:49:10
【问题描述】:
我们有一个用 WPF 编写的应用程序。 我正在尝试为在后台线程上运行的一些代码编写单元测试。在这段代码的一些地方,我们需要在 UI 线程上做一些事情。在这些地方我们使用以下代码结构:
Application.Current.Dispatcher.Invoke(new Action(() =>
{
// do something on UI thread
}));
当我创建一个异步单元测试时,它似乎卡在了 Invoke 方法上。我想这是因为调度员没有“调度”。我试图通过使用一个名为 DisaptcherUtil 的类来解决这个问题,该类在 Internet 上的许多地方都被引用。但我无法让它工作。我的代码的简化版本现在如下所示:
[TestMethod]
public async Task TestDispatcher()
{
new Application();
DispatcherUtil.DoEvents();
await Task.Run(() => MethodUsingDispatcher());
}
private void MethodUsingDispatcher()
{
Application.Current.Dispatcher.Invoke(new Action(() =>
{
Console.WriteLine("On the dispatchee thread!");
}));
Console.WriteLine("BAck to background trhead");
}
public static class DispatcherUtil
{
[SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
public static void DoEvents()
{
DispatcherFrame frame = new DispatcherFrame();
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background,
new DispatcherOperationCallback(ExitFrame), frame);
Dispatcher.PushFrame(frame);
}
private static object ExitFrame(object frame)
{
Console.WriteLine("ExitFrame");
((DispatcherFrame)frame).Continue = false;
return null;
}
}
当我运行名为“TestDispatcher”的测试时,它只是挂起。
有人知道为什么会这样吗?这是执行此操作的正确方法吗,还是我应该沿着为 Dispatcher 创建一个可以在测试中模拟的接口的路线走下去。我在一些地方看到过这种做法。
【问题讨论】:
-
您不应该在可测试的类中调用任何静态方法。使用定义
Invoke方法的接口注入类,并通过该接口调用Dispatcher.Invoke方法,而不是直接调用静态Dispatcher.Invoke方法。您可以轻松地在单元测试中替换接口的实现。
标签: c# wpf multithreading mstest dispatcher