Task 异步小技巧
原文地址:Task 异步小技巧 - 一事冇诚 - 博客园 (cnblogs.com)
async Task 语法糖出来后,异步编程变得非常简单,适合需要耗费较长时间的任务。
有些小伙伴使用后可能会非常疑惑,使用异步和同步,在耗时上几乎没有差别。
下面我们看一个例子,场景是需要调用多个第三方的WebApi,分别是获取名称、年龄、性别,由于网络环境等原因,api响应时间可能会接近1秒
1 public async Task Test() 2 { 3 var sw = new Stopwatch(); 4 sw.Start(); 5 6 var userName = await GetUserNameAsync(); 7 var userAge = await GetUserAgeAsync(); 8 var userSex = await GetUserSexAsync(); 9 10 sw.Stop(); 11 var ts = sw.Elapsed; 12 Console.WriteLine($"总共耗时:{ts.TotalMilliseconds}ms"); 13 } 14 15 private async Task<string> GetUserNameAsync() 16 { 17 await Task.Delay(500); 18 return "小明"; 19 } 20 21 private async Task<string> GetUserAgeAsync() 22 { 23 await Task.Delay(800); 24 return "11"; 25 } 26 27 private async Task<string> GetUserSexAsync() 28 { 29 await Task.Delay(900); 30 return "11"; 31 }
运行后发现,这个时间2秒多,这用户体验肯定是无法忍受的
导致这样结果的原因是每次进行异步调用的时候,都在异步函数前加上了 await ,对于单单这个过程来说,其实相当于同步,等待直到结果返回,每个异步函数都await,时间自然就叠加了,为了解决这个问题,使用一个小技巧,可以将代码改成下面这样
1 public async Task Test() 2 { 3 var sw = new Stopwatch(); 4 sw.Start(); 5 6 var userNameTask = GetUserNameAsync(); 7 var userAgeTask = GetUserAgeAsync(); 8 var userSexTask = GetUserSexAsync(); 9 10 var userName = await userNameTask; 11 var userAge = await userAgeTask; 12 var userSex = await userSexTask; 13 14 sw.Stop(); 15 var ts = sw.Elapsed; 16 Console.WriteLine($"总共耗时:{ts.TotalMilliseconds}ms"); 17 } 18 19 private async Task<string> GetUserNameAsync() 20 { 21 await Task.Delay(500); 22 return "小明"; 23 } 24 25 private async Task<string> GetUserAgeAsync() 26 { 27 await Task.Delay(800); 28 return "11"; 29 } 30 31 private async Task<string> GetUserSexAsync() 32 { 33 await Task.Delay(900); 34 return "11"; 35 }
这次运行的总耗时,就是3个异步中,耗时最长那个 GetUserSexAsync
为什么会这样呢,这个小技巧的关键是这里,当执行到异步函数的时候,不加 await,不进行等待,让这些任务乖乖在别的线程的执行,当需要用到他们的时候,再去等待返回值,所以时间上不会进行叠加,哪个最长,总耗时就是哪个
1 var userNameTask = GetUserNameAsync(); 2 var userAgeTask = GetUserAgeAsync(); 3 var userSexTask = GetUserSexAsync(); 4 5 var userName = await userNameTask; 6 var userAge = await userAgeTask; 7 var userSex = await userSexTask;
有不对、不好的地方请大佬们指正,我会改正过来,感谢各位大佬
本文来自博客园,作者:一事冇诚,转载请注明原文链接:https://www.cnblogs.com/ysmc/p/15409898.html