gpt4 book ai didi

winforms - 如果存在 System.Windows.Forms.Form 实例,await Task.Delay(...) 会卡住

转载 作者:行者123 更新时间:2023-12-03 09:27:59 25 4
gpt4 key购买 nike

如果作为控制台应用程序运行,以下程序将卡在 DoTheStuff().Wait(); 行上:

namespace Test
{
using System.Threading.Tasks;
using System.Windows.Forms;

class Program
{
static void Main(string[] args)
{
new Form();
DoTheStuff().Wait();
}

private static async Task DoTheStuff()
{
await Task.Delay(1000);
}
}
}

如果您注释掉 new Form(); 行,它就会按预期工作。 (运行1秒,然后退出)。如何保持预期行为并仍然拥有 Form 实例?

现在,如果您有兴趣,请了解一些背景知识:

我有一个作为 Windows 服务托管的应用程序(在本地测试时作为控制台)。

它需要访问 SystemEvents.TimeChanged 事件。

但是,根据 documentation ,这仅在具有 Windows 窗体时有效(因此不适用于服务或控制台应用程序)。链接文档中提供了一种解决方法,其中包括创建隐藏表单。

不幸的是,程序现在完全卡住了,这是由await 和Form 实例相结合造成的。

那么,在访问 SystemEvents.TimeChanged 事件时,我到底如何才能保持预期的异步/等待行为呢?


感谢下面的帮助,这里是修改后的代码,可以在不卡住的情况下工作:

namespace Test
{
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

class Program
{
static void Main(string[] args)
{
new Thread(() => Application.Run(new Form())).Start();
// SynchronizationContext.SetSynchronizationContext(null);
DoTheStuff().Wait();
}

private static async Task DoTheStuff()
{
await Task.Delay(1000);
}
}
}

在我的程序中,我需要使用“SynchronizationContext.SetSynchronizationContext(null);”,因为线程池应该用于等待任务。我认为这不是一个好的做法,因为 Form 显然初始化它是有原因的。但是在没有用户输入的情况下运行隐藏的表单(它是一项服务!),现在看不到任何危害。

documentation感觉有点不完整,MS 甚至没有提到使用示例 2 可能出现的问题(await/async 在实例化 Form 时隐式改变行为)。

最佳答案

这是设计使然。创建新的 Form 对象让 Winforms 管道安装新的 SynchronizationContext。通过查看 SynchronizationContext.Current 属性,您可以在调试器中看到一些内容。

每当您异步执行任何操作时,该属性都很重要。如果为 null(默认值),则使用 wait 获取在线程池线程上运行的代码。如果不是,则等待管道将通过调用 SynchronizationContext.Post() 方法来实现等待。这确保您的代码在主线程上运行。

但这在你的程序中不起作用,因为你违反了契约(Contract)。您没有调用Application.Run()。必填。

SystemEvents 类将创建自己的隐藏通知窗口,并在您不提供消息循环时泵送消息循环。无需创建表单。结果是它的事件将在任意线程上触发,而不是在您的主线程上。因此,请务必注意锁定要求。

关于winforms - 如果存在 System.Windows.Forms.Form 实例,await Task.Delay(...) 会卡住,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16277850/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com