简述

Task.Wait() 会阻止线程,在等待期间,系统不会对其它操作进行反应。Task.Wait() 是一种同步方法,该方法使调用线程等待当前任务实例完成,直到发生以下情况之一:

  • 任务成功完成。
  • 任务本身被取消或引发异常。 在这种情况下,您将处理 AggregateException 异常。 AggregateException.InnerExceptions属性包含有关异常的详细信息。
  • 所定义的间隔 millisecondsTimeout 。 在这种情况下,当前线程将继续执行,并且该方法将返回 false

await 只是等待当前任务完成,在等待期间可以响应系统的其它操作。await 运算符暂停对其所属的 async 方法的求值,直到其操作数表示的异步操作完成。异步操作完成后,await 运算符将返回操作的结果(如果有)。await必须用来修饰Task或Task,而且只能出现在已经用async关键字修饰的异步方法中。通常情况下,async/await成对出现才有意义。

应用

Task.Wait() 使用案例

下面的示例启动了一个任务,该任务生成0到100之间的5000000随机整数,并计算其平均值。 该示例使用 Wait(Int32) 方法等待应用程序在150毫秒内完成。 如果应用程序正常完成,任务会显示其生成的随机数字的总和和平均值。 如果超时间隔已过,则该示例在消息终止之前显示一条消息。

  1. public static void Main()
  2. {
  3. Task t = Task.Run(() => {
  4. Random rnd = new Random();
  5. long sum = 0;
  6. int n = 5000000;
  7. for (int ctr = 1; ctr <= n; ctr++)
  8. {
  9. int number = rnd.Next(0, 101);
  10. sum += number;
  11. }
  12. Console.WriteLine("Total: {0:N0}", sum);
  13. Console.WriteLine("Mean: {0:N2}", sum / n);
  14. Console.WriteLine("N: {0:N0}", n);
  15. });
  16. TimeSpan ts = TimeSpan.FromMilliseconds(150);
  17. if (!t.Wait(ts))
  18. Console.WriteLine("The timeout interval elapsed.");
  19. }

执行结果:
C# Task.Wait() 和 await 的区别和应用 - 图1

await 使用案例

  1. static void Main(string[] args)
  2. {
  3. Console.WriteLine("-------主线程启动-------");
  4. Task<int> task = GetStrLengthAsync();
  5. Console.WriteLine("主线程继续执行");
  6. Console.WriteLine("Task返回的值" + task.Result);
  7. Console.WriteLine("-------主线程结束-------");
  8. }
  9. static async Task<int> GetStrLengthAsync()
  10. {
  11. Console.WriteLine("GetStrLengthAsync方法开始执行");
  12. //此处返回的<string>中的字符串类型,而不是Task<string>
  13. string str = await GetString();
  14. Console.WriteLine("GetStrLengthAsync方法执行结束");
  15. return str.Length;
  16. }
  17. static Task<string> GetString()
  18. {
  19.    //Console.WriteLine("GetString方法开始执行")
  20. return Task<string>.Run(() =>
  21. {
  22. Thread.Sleep(2000);
  23. return "GetString的返回值";
  24. });
  25. }

执行结果
C# Task.Wait() 和 await 的区别和应用 - 图2
可以看出来,main函数调用GetStrLengthAsync方法后,在await之前,都是同步执行的,直到遇到await关键字,main函数才返回继续执行。
那么是否是在遇到await关键字的时候程序自动开启了一个后台线程去执行GetString方法呢?
现在把GetString方法中的那行注释加上,运行的结果是:
C# Task.Wait() 和 await 的区别和应用 - 图3
大家可以看到,在遇到await关键字后,没有继续执行GetStrLengthAsync方法后面的操作,也没有马上反回到main函数中,而是执行了GetString的第一行,以此可以判断await这里并没有开启新的线程去执行GetString方法,而是以同步的方式让GetString方法执行,等到执行到GetString方法中的Task.Run()的时候才由Task开启了后台线程!

参考1 :https://docs.microsoft.com/zh-cn/dotnet/
参考2:https://www.cnblogs.com/xtjatswc/p/12213299.html