加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

winforms – 为什么在等待WindowsFormsSynchronizationContext时

发布时间:2020-12-15 04:16:18 所属栏目:Java 来源:网络整理
导读:我有一个自定义的 Windows窗体控件,其中包含MSTest单元测试.我在这个类中添加了一个异步方法,我需要覆盖它,但新测试总是超时. 经过一些实验,我把问题简化为控制创建和等待. [TestMethod]public async Task TestMethod1(){ Control c = new Control(); await
我有一个自定义的 Windows窗体控件,其中包含MSTest单元测试.我在这个类中添加了一个异步方法,我需要覆盖它,但新测试总是超时.

经过一些实验,我把问题简化为控制创建和等待.

[TestMethod]
public async Task TestMethod1()
{
    Control c = new Control();
    await Task.Delay(1);
}

我注意到测试以SynchronizationContext.Current设置为null开始,然后一旦创建控件,它就会更改为WindowsFormsSynchronizationContext.如果我强制同步上下文返回null,则测试将通过.

[TestMethod]
public async Task TestMethod1()
{
    Control c = new Control();
    SynchronizationContext.SetSynchronizationContext(null);
    await Task.Delay(1);
}

有没有办法在不阻塞的情况下从WindowsFormsSynchronizationContext使用await?

解决方法

Windows窗体控件假定它们在Windows窗体应用程序中运行,而单元测试则不然.这就是你的单元测试挂起的原因.

更具体地说,WinForms控件安装一个WindowsFormsSynchronizationContext,它将工作委托给Application.Run中的Win32消息循环.因此,您的异步方法会查看上下文并将其继续排入该消息循环.但是,没有实际的消息循环,因为您的单元测试不会调用Application.Run.

最好的解决方案IMO是使用MVVM模式,您不在UI应用程序之外测试UI元素,因此您永远不会遇到这种情况(在MVVM中,您需要对逻辑UI进行单元测试,而不是文字UI).使用MVVM方法,您的代码将如下所示:

[TestMethod]
public async Task TestMethod1()
{
  ViewModel vm = new ViewModel();
  await vm.MethodAsync();
}

但是,如果您确实需要对实际UI元素进行单元测试,则可以使用Async CTP中包含的类似Windows Forms Context的类型:

[TestMethod]
public async Task TestMethod1()
{
    await WindowsFormsContext.Run(async () =>
    {
        Control c = new Control();
        await Task.Delay(1);
    });
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读