NUnit 异步测试 + RequiresSTA => 等待不返回 STA 线程
本文关键字:等待 返回 STA 线程 异步 测试 RequiresSTA NUnit | 更新日期: 2023-09-27 18:31:35
下面的代码:
[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
然后,在新的 FrameworkElement() 上抛出一个 InvalidOperationException。
NUnit支持STA线程创建,现在支持异步测试,但它似乎没有通过创建MTA SynchronizationContext来混合这两种模式。
我如何让它工作?有什么解决方法吗?
我的AsyncEx
库中的AsyncContext
,该库最初是为支持单元测试而编写的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();
});
}
我设法解决了这个问题。但是,我敢肯定,关于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,它们也不是同一个线程
请注意在等待之前实例化控件,并在等待之后使用它们。只需要做一些调整就可以直接切换到主线程(我们可以想象一个"using(await StaSynchronizationContext.Create())",这将使我们在开始时切换到线程 12)