1

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

/// <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));
                }
            });
        }
    }

当我点击按钮程序执行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() 等待,我的测试将无休止地运行并且从未完成

4

1 回答 1

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");
}

如果您现在更改InvokeBeginInvoke调用不再同步并且一切正常。

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));
        }
    });
}
于 2013-04-16T14:00:13.330 回答