等待一个方法与等待一个任务






3.58/5 (10投票s)
等待方法与等待任务
大多数开发者只是等待方法,而不是等待awaiter返回的Task。awaiter是由被等待的方法返回的东西。
在这篇文章中,我们将研究当我们在方法中多次等待时,等待方法而不是等待任务会发生什么。
用例
在调用代码中有两个可等待的方法,它们可以单独处理。这意味着当第一个await正在发生时,可以发生第二个可等待的调用。
所有的awaiter和awaitable有点令人困惑。如果你不理解这句话,请再读一遍。
开始编码
为了本文的目的,我将在一个控制台应用程序中测试这一点。这是我们的AwaitTest类。
public class AwaitTest { public async Task DoSomeThingAsync() { var time = Stopwatch.StartNew(); //a database call which takes 5 seconds to run await Task.Delay(5000); await PerformCalculationsAsync(); Console.WriteLine("time taken : " + time.Elapsed); } private async Task<int> PerformCalculationsAsync() { await Task.Delay(2000); //This can be some operation which takes 2 sec. return 30; } }
所以,我们的DoSomethingAsync()
有两个awaitable。一个需要5秒执行,另一个需要2秒执行。现在,我们将在应用程序的Main
方法中调用它,看看它是如何进行的。
以下是如何在应用程序的Main
方法中调用我们的async
方法。
public class Program { static void Main(string[] args) { AwaitTest at = new AwaitTest(); at.DoSomeThingAsync().GetAwaiter().GetResult(); } }
在DoSomeThingAsync()
方法中使用上面的代码,你能猜出操作的计时吗?
那么,DoSomeThingAsync()
完成操作所需的时间是
Time taken : 00:00:07.0079634
那么,当我们等待方法时发生了什么?
它本质上就是这样,但我们需要理解它是如何工作的。因此,当一个方法被等待时,它会等待该方法完成其操作。
我们在DoSomeThingAsync()
方法中的第一个awaiter
await Task.Delay(5000);
上面的行只是等待5秒钟完成其操作。完成操作后,将执行下一个awaiter。
await PerformCalculations();
上面的行需要2秒才能完成其操作。所以这次操作的总时间是07.0079634。
我建议你自己尝试一下,只需在DoSomeThingAsync()方法中放置一个调试器,然后观察它在做什么。
现在使用上面的方法,它看起来就像同步操作一样,因为一次只执行一件事。因此,我们没有获得async-await的好处。
好的,什么会更好?
与其直接等待方法,不如等待Task而不是方法。
我将修改DoSomeThingAsync()
方法,以便我们等待Task
。
public async Task DoSomeThingAsync() { var time = Stopwatch.StartNew(); //a database call which takes 5 seconds to run //await Task.Delay(5000); //await PerformCalculationsAsync(); Task t1 = Task.Delay(5000); Task t2 = PerformCalculationsAsync(); await t1; await t2; Console.WriteLine("time taken : " + time.Elapsed); }
现在,猜猜时间。这是输出
time taken : 00:00:05.0080029
现在改变计时的是什么?
让我们看看代码中发生了什么。
Task t1 = Task.Delay(5000);
Task t2 = PerformCalculationsAsync();
调试时,上面两行会立即返回(但这并不意味着这两个操作没有完成)。相反,t1
和t2
将返回它们自己的Task
。
await t1;
await t2;
当执行第一个await t1;
时,它返回一个Task
,然后第二个await t2;
将开始执行。因此,在第一个任务完成时,第二个任务将会完成,因为第二个任务需要2秒,而第一个任务需要5秒才能完成。
因此,我们执行的总时间将为5秒。
总结
如果我们在方法中有多个等待方法要执行,最好将它们作为Task,而不是等待一个。考虑对方法的执行顺序进行排序,以便我们可以为其他操作节省一些时间。
在本文中可能只有2秒钟,但在现实世界中,2秒钟是一段很长的时间,并且会存在性能问题。
或者,您可以使用Task.WhenAll
方法来等待所有awaitable完成其操作。
感谢阅读!