微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Dispatcher.Invoke在NUnit测试中引发TaskCanceledException

如何解决Dispatcher.Invoke在NUnit测试中引发TaskCanceledException

我正在尝试通过使用接口从我们的视图模型中提取dispatcher。我已经创建了该接口的模拟实现,如下所示:

public class MockIdispatcher : Idispatcher,Idisposable
{
    public MockIdispatcher()
    {
        var dispatcherThread = new Thread(dispatcher.Run) { IsBackground = true };
        dispatcherThread.SetApartmentState(ApartmentState.STA);
        dispatcherThread.Start();

        while ((dispatcher = dispatcher.FromThread(dispatcherThread)) == null) Thread.Yield();  // need to wait until the thread we created has started its dispatcher
    }

    internal dispatcher dispatcher { get; }

    /* ... more implementation here */
}

我已经创建了一个虚拟的NUnit测试,如下所示,但是对dispatcher.Invoke()调用抛出了TaskCanceledException

[Test]
public void TestPoc()
{
    var foo = new MockIdispatcher();
    foo.dispatcher.Invoke(() =>
    {
        Debug.WriteLine("hey there!");
    });
}

有关如何使此代码正常工作的任何建议?我实际上想在幕后使用dispatcher,以便更轻松地玩SynchronizationContext之类的东西。

解决方法

问题似乎与如何在构造函数中获得Dispatcher有关。我如下所示更改了构造函数,从而解决了该问题。看来您可能需要先实际在线程上调用Dispatcher.CurrentDispatcher。仅仅调用Dispatcher.Run()即可。

public MockIDispatcher()
{
    using (var mre = new ManualResetEvent(false))
    {
        Dispatcher dispatcher = null;
        var dispatcherThread = new Thread(() =>
        {
            dispatcher = Dispatcher.CurrentDispatcher;
// ReSharper disable once AccessToDisposedClosure Not Possible because we are waiting inside the using loop
            mre.Set();
            try { Dispatcher.Run(); } catch {  /* swallow exceptions */ }
        }) { IsBackground = true };

        dispatcherThread.SetApartmentState(ApartmentState.STA);
        dispatcherThread.Start();

        mre.WaitOne();
        Dispatcher = dispatcher;
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。