在单元测试中等待任务完成

时间:2013-04-16 08:50:32

标签: .net wpf unit-testing dispatcher

我有一个简单的窗口,其中Button和TextBox名为 SimpleText

/// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

        }

        private void ButtonClicked(object sender, RoutedEventArgs e)
        {
            TestMe();

        }

        public Task TestMe()
        {
            return Task.Factory.StartNew(() =>
            {
                for (int i = 0; i <= 11000; i++)
                {
                    var text = i;
                    SimpleText.Dispatcher.Invoke(() => SimpleText.Text = text.ToString(CultureInfo.InvariantCulture));
                }
            });
        }
    }

当我点击按钮程序exectute ButtonClicked 时 然后我决定测试这段代码

        [TestMethod]
        public void TestMethod1()
        {
            var mainWindow = new MainWindow();
            Assert.IsNotNull(mainWindow);


            var task =  mainWindow.TestMe();
            DispatcherUtil.DoEvents();

            Assert.AreEqual(mainWindow.SimpleText.Text, "11000");
        }

DispatcherUtil 是帮助程序类。帮我从调度员队列中做事件

public static class DispatcherUtil
    {
        [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
        public static void DoEvents()
        {
            var frame = new DispatcherFrame();
            Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background,
                new DispatcherOperationCallback(ExitFrame), frame);
            Dispatcher.PushFrame(frame);
        }

        private static object ExitFrame(object frame)
        {
            ((DispatcherFrame)frame).Continue = false;
            return null;
        }
    }

我的测试下降了文本框值“34”。有时测试值为“56”。因此我需要等待所有队列完成。我怎么能这样做?

如果我等了task.Wait()我的测试正在运行而没有结束,从未完成

1 个答案:

答案 0 :(得分:0)

好的我知道这里发生了什么:你的测试方法和SimpleText.Dispatcher在同一个线程上运行,这意味着如果你调用SimpleText.Dispatcher.Invoke然后task.Wait()你有一个经典的死锁:

[TestMethod]
public void TestMethod1()
{
    var mainWindow = new MainWindow();
    Assert.IsNotNull(mainWindow);

    var task =  mainWindow.TestMe();
    DispatcherUtil.DoEvents(); // synchronously invokes onto this thread
    task.Wait(); // blocks this thread so DoEvents is blocked (I've added this).

    Assert.AreEqual(mainWindow.SimpleText.Text, "11000");
}

如果您现在将Invoke更改为BeginInvoke,则通话将不再同步,一切正常。

public Task TestMe()
{
    return Task.Factory.StartNew(() =>
    {
        for (int i = 0; i <= 11000; i++)
        {
            var text = i;
            SimpleText.Dispatcher.BeginInvoke( 
                // this is now asynchronous so non-blocking
                () => SimpleText.Text = 
                         text.ToString(CultureInfo.InvariantCulture));
        }
    });
}
相关问题