c# - 为什么同步控制台 Main Method 挂起调用异步方法?
问题描述
我无法理解为什么从控制台应用程序的 Main 方法调用异步方法会永远挂起。我觉得我错过了异步执行的一些关键元素:
static void Main(string[] args)
{
Console.WriteLine("w3");
var exe = new Exe2();
exe.Do2().Wait();
Console.WriteLine("/w3");
Console.ReadKey();
}
public class Exe2
{
public async Task Do2()
{
Task task1 = new Task(() => { Console.WriteLine("t1"); Task.Delay(2000); });
Task task2 = new Task(() => { Console.WriteLine("t2"); Task.Delay(2000); });
Task task3 = new Task(() => { Console.WriteLine("t3"); Task.Delay(2000); });
await Task.WhenAll(task1, task2, task3);
}
}
上面的代码打印 w3 没有别的,也没有采用ReadKey
任何一个。
解决方案
你还没有开始你的任务,Task.WhenAll
本质上是要永远等待。你需要打电话Start
启动 Task,将其调度到当前 TaskScheduler 执行。
task1.Start();
task2.Start();
task3.Start();
await Task.WhenAll(task1, task2, task3);
然而:除非你绝对知道你需要它,否则永远不要使用Task
构造函数,它对于没有经验的编码人员有几个非常大的陷阱,例如只支持动作委托并且需要启动。相反,总是使用whichTask.Run
将启动您的任务
Task task1 = Task.Run(() => { Console.WriteLine("t1"); Task.Delay(2000); });
Task task2 = Task.Run(() => { Console.WriteLine("t2"); Task.Delay(2000); });
Task task3 = Task.Run(() => { Console.WriteLine("t3"); Task.Delay(2000); });
尽管不是您的问题,但您永远不需要在现代 .net中调用Wait
或调用异步方法。相反,使用异步重载Result
Main
static async Task Main(string[] args)
{
Console.WriteLine("w3");
var exe = new Exe2();
await exe.Do2();
Console.WriteLine("/w3");
Console.ReadKey();
}
推荐阅读
- python - 解析、删除和屏蔽 IP 地址的脚本
- python - Pandas:如何将一系列函数应用于多对列
- rest - Curl POST 将 Null 值插入到表中以用于连接列
- java - REST API 设计查询 2
- php - 如何在 php 中创建多部分/混合的电子邮件内容类型
- sql - 如果第 2 个表中存在 1 个表的值,则用第 1 个和第 2 个表的总和更新第 2 个表的值,否则将第 1 个表的数据插入到第 2 个表
- visual-studio - UWP 不会在 Microsoft 示例中为 FileIO.WriteBufferAsync 编译 GetBufferFromString
- c# - 将单个项目的方法标记为已过时
- java - Python和Java中的矩阵减法差异
- csv - 使用 Bridge 将 CSV 数据导入 IPTC XMP 图像的元数据映射