gpt4 book ai didi

c# - await Task.Run(...) 对控制台和 Windows 应用程序的行为不同

转载 作者:行者123 更新时间:2023-12-02 04:44:20 25 4
gpt4 key购买 nike

我有一个包含以下代码的控制台应用程序

static void Main(string[] args) {
Method();
Console.ReadKey();
}

private static void Method() {
Task t = DoSomething();
t.Wait();
Console.WriteLine("Finished");
}

private static async Task DoSomething() {
await Task.Run(() =>
Thread.Sleep(1000));
}

一切都按照我的预期运行,控制台在运行该程序一秒钟后显示“已完成”。当我将相同的代码移动到 Windows 应用程序中时,我发现该程序刚刚停止

private void button1_Click(object sender, EventArgs e) {
Task t = DoSomething();
t.Wait();
MessageBox.Show("Finished");
}

private static async Task DoSomething() {
await Task.Run(() =>
Thread.Sleep(1000));
}

调试器显示当前执行行是 t.Wait(),即使在 DoSomething 方法中的任务已经运行之后。

是否需要在 Windows 应用程序中执行一些我不需要在控制台应用程序中执行的不同操作?还是我从根本上误解了什么?

最佳答案

这是经常发生的事情。你造成了僵局。

简而言之,像 WinForms 和 WPF 这样的框架“强制执行”线程同步上下文,这意味着每当您启动一个新任务时,您的代码的其余部分将在它启动时的同一个线程上继续运行。这样做是为了确保,例如,在 UI 线程上启动的代码在任务返回后将继续在同一线程上运行。

因为您在任务上阻塞(使用Wait 方法),并且任务正在尝试向阻塞线程返回一个值,所以两个线程都进入死锁状态。

此行为不会发生在控制台应用程序中,因为没有强制执行线程同步上下文,任务的继续可以在完全不同的第三个线程上运行。

Stephen Cleary 在这里很好地解释了这一点:http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html

关于c# - await Task.Run(...) 对控制台和 Windows 应用程序的行为不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20123152/

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