在主线程上调用 Application.DoEvents 与在 ThreadPool 中一样吗?

Is calling Application.DoEvents on main thread same as in ThreadPool?

我们尝试对一些旧的遗留代码进行自动化测试。有一个打开的表格,运行 定时器并从端口读取数据。 unittest 打开表单,但计时器直到 Application.DoEvents 开始处理 windows 消息队列才开始计时。它是不同的,因为它是从 unittest 执行的并且 Application.Run 不是代码的一部分。

但是我们不能通过Application.DoEvents阻塞unittest线程,因为我们需要等待并通过断言检查数据。

ThreadPool.QueueUserWorkItem(x =>
{
    While(!form.workFinished)
    { 
         Application.DoEvents();
         Thread.Sleep(50);
    }
    synchronization.Set();
});
synchronization.WaitOne();

Assert.AreEqual(10000, form.recorded.Count);

但是这段代码没有达到我的预期。它与从 WinForm 应用程序执行表单不同吗?我可以从线程池调用 Application.DoEvents 吗?

我真的不想真的不修改遗留代码。我只需要让 unittest 处理当前的解决方案。

最好的方法是 运行 通常使用 Application.Run 的表格。测试完成后关闭表单或在该线程.

上调用Application.Exit

DoEvents 在当前线程上抽取事件。可以有多个 UI 线程。 DoEvents只影响当前的

您的单元测试代码可能如下所示:

Form form = null;
var task = Task.Factory.StartNew(() => {
 form = new Form(); //Run ctor on UI thread.
 Application.Run(form);
}, LongRunning);

//Work with the form here.

form.Invoke(() => Application.Exit());
task.Wait();

这只是草图。缺少同步,我相信还有其他问题需要解决。

LongRunning 确保 GUI 运行 每次都在新线程上。这可以防止状态从一个测试泄漏到另一个测试。

基本上,这是标准的 UI 线程加工作线程模型。这里单元测试线程是worker,需要创建UI线程。通常,UI 线程将是 Main 线程,并且将创建 worker。