我想知道为什么我们需要 C# 中的异步函数。我做了研究,如果有一个 IO 密集型任务想要等待而不阻塞,看起来会使用异步函数。
public class HelloWorld
{
public static async Task DoIO()
{
await Task.Delay(1000, new CancellationTokenSource().Token);
Console.WriteLine("DONE");
}
public static void Main(string[] args)
{
DoIO();
Console.WriteLine("Start");
while (true);
// Output: Start \n DONE
}
}
另一种情况是当一个CPU密集型任务要启动,但我们不想等待它时。它应该在后台运行。它看起来与之前的代码块一模一样,但将
DoIO()
替换为 DoCPU()
,这是一个需要大量计算的函数。
public static async Task DoCPU()
{
await Task.Run(() => {
// Heavy computation
});
}
在这两种情况下,关键字都是“无需等待”。我们希望调用异步方法而不阻塞调用者方法。
现在这就是我的问题出现的地方:为什么我会收到警告“因为不等待此调用,所以在调用完成之前继续执行当前方法。考虑将“await”运算符应用于调用?” 异步函数的全部目的不就是 NOT wait 吗?否则为什么不直接使用默认阻塞的“常规”同步方法呢?
您收到警告是因为未等待
DoIO
。这可能会导致主线程完成 Main
方法,从而在打印“Done”之前终止进程。在您的示例中,您添加了一个无限循环来防止这种情况,但这不是解决问题的最佳方法。
它应该看起来像:
public static async Task Main(string[] args)
{
Console.WriteLine("Start");
await DoIO();
Console.WriteLine("DoIO completed");
}
这允许程序按预期顺序运行所有内容。但对于像这样的简单控制台程序来说,异步的优点相当小,当使用常规的旧同步方法时,您会得到完全相同的行为。异步的主要优点是:
请注意,异步编程不需要 async/await。您可以使用其他方法做同样的事情。但 async/await 让它变得更加容易。