4

下面的代码:

    [RequiresSTA]
    [Test]
    public async Task TestSta()
    {
        Console.WriteLine(Thread.CurrentThread.ManagedThreadId+" - "+Thread.CurrentThread.GetApartmentState());
        // *** await something here ***
        Console.WriteLine(Thread.CurrentThread.ManagedThreadId+" - "+Thread.CurrentThread.GetApartmentState());
        new FrameworkElement();
    }

产生以下输出:

9 - STA

12 - MTA

然后,在 new FrameworkElement() 上引发 InvalidOperationException。

NUnit 支持 STA 线程创建,现在支持异步测试,但似乎并没有通过创建 MTA SynchronizationContext 来混合两种模式。

我如何让这个工作?任何解决方法?

4

2 回答 2

3

您可以使用AsyncContextfrom my AsyncExlibrary,它最初是为了async在单元测试库支持单元测试之前支持单元测试而编写的。

[RequiresSTA]
[Test]
public Task TestSta()
{
  AsyncContext.Run(async () =>
  {
    Console.WriteLine(Thread.CurrentThread.ManagedThreadId+" - "+Thread.CurrentThread.GetApartmentState());
    // *** await something here ***
    Console.WriteLine(Thread.CurrentThread.ManagedThreadId+" - "+Thread.CurrentThread.GetApartmentState());
    new FrameworkElement();
  });
}
于 2013-09-16T23:25:07.593 回答
0

我设法解决了这个问题。但是,我确信在 stackoverflow 上的帖子会让我非常头疼:) 请参阅下面的答案。

一篇关于 SynchronizationContext 的非常好的文章(单击此处)刚刚给了我所需的代码(和知识)。

但是,我不得不稍微调整一下以避免 StaSynchronizationContext 处理的死锁,并在工作线程内传播同步上下文。

我的测试现在如下所示:

    [Test]
    [RequiresSTA]
    public async Task DoSomeUITest()
    {
        using (new StaSynchronizationContext())
        {
            Console.WriteLine(Thread.CurrentThread.ManagedThreadId + " - " + Thread.CurrentThread.GetApartmentState());
            // *** await something here ***
            Console.WriteLine(Thread.CurrentThread.ManagedThreadId + " - " + Thread.CurrentThread.GetApartmentState());
            new FrameworkElement();
        }
    }

现在输出:

9 - STA

12 - STA

... 问题解决了 !

在此处下载调整后的代码

* 编辑和免责声明 * 在等待之前,您的代码将在 NUnit 创建的 STA 线程上运行。(线程 9)在第一次等待之后,代码将在 StaSynchronizationContext(线程 12)创建的线程上运行:即使它们都是 STA ,它们也不是同一个线程

请注意在等待之前实例化控件,并在之后使用它们。只需要更多的调整来直接切换到主线程(我们可以想象一个“使用(等待 StaSynchronizationContext.Create())”,这将使我们在开始时打开线程 12)

于 2013-09-16T22:07:39.897 回答