1、涉及内容html
async & await是C# 5.0引入的,控制台输出所使用的$符号(拼接字符串)是C# 6.0引入的,其功能相似于string.Format()方法。多线程
2、多线程、异步、同步之间的联系与区别异步
厨房案例:async
好比说你要炒5道菜ABCDE,可是只有两个炉子能够用,即同时只能炒两道菜。在这里,炉子就是线程。ide
假如两个炉子分别同时炒A和B,那剩下的CDE只能等A或B炒完了才能开始。这个等待的过程就是同步,咱们称之为阻塞,即这个时候你只能炒A和B这两道菜。网站
假如你还有一台咖啡机,在你炒A和B的时候顺手把咖啡豆和水放到咖啡机里打开开关,而后你就不用管它了。此时,就是新开了一个线程去煮咖啡,而煮咖啡atom
是由咖啡机自动完成的并不影响继续炒菜,因此煮咖啡这个线程是异步的,咱们称之为非阻塞。url
当咖啡机叮的一声通知你咖啡已经煮好了,你要去把咖啡拿出来加点糖或奶什么的,这个拿咖啡的动做咱们称之为回调,这个是咖啡机线程完成以后通知你要去spa
作的动做。pwa
简单来讲:
会占用你的时间让你没法去作其它事情的任务叫作同步任务(炒菜要专一不然会糊锅)。
那些不须要占用你的时间的任务叫作异步任务(咖啡机本身会把咖啡煮好,不须要你一直看着它)。
下面代码演示不使用异步的状况:
class Program { //建立计时器 private static readonly Stopwatch stopwatch = new Stopwatch(); static void Main(string[] args) { #region async & await入门之不使用异步 //启动计时器 stopwatch.Start(); //URL地址 const string url1 = "http://www.cnblogs.com/"; const string url2 = "http://www.cnblogs.com/atomy/"; //异步下载某网站内容,并统计字符的个数。 var result1 = CountCharacters("url1", url1); var result2 = CountCharacters("url2", url2); //主要是经过拼接字符串达到耗时操做 for (var i = 0; i < 3; i++) { ExtraOperation(i + 1); } //控制台输出 Console.WriteLine($"{url1} 的字符个数:{result1}"); Console.WriteLine($"{url2} 的字符个数:{result2}"); Console.WriteLine($"总耗时{stopwatch.ElapsedMilliseconds}ms。"); Console.Read(); #endregion } /// <summary> /// 统计字符个数 /// </summary> /// <param name="id"></param> /// <param name="address"></param> /// <returns></returns> private static int CountCharacters(string name, string address) { var wc = new WebClient(); Console.WriteLine($"{name}开始调用,历时{stopwatch.ElapsedMilliseconds}ms,线程id={Thread.CurrentThread.ManagedThreadId}。"); var result = wc.DownloadString(address); Console.WriteLine($"{name}调用完成,历时{stopwatch.ElapsedMilliseconds}ms,线程id={Thread.CurrentThread.ManagedThreadId}。"); return result.Length; } /// <summary> /// 额外操做 /// </summary> /// <param name="id"></param> private static void ExtraOperation(int id) { //这里是经过拼接字符串进行一些相对耗时的操做 var s = ""; for (var i = 0; i < 6000; i++) { s += i; } Console.WriteLine($"第{id}次ExtraOperation执行完成,历时:{stopwatch.ElapsedMilliseconds}ms。"); } }
运行结果以下:
下面代码演示使用异步的状况:
class Program { //建立计时器 private static readonly Stopwatch stopwatch = new Stopwatch(); static void Main(string[] args) { #region async & await入门之使用异步 //启动计时器 stopwatch.Start(); //URL地址 const string url1 = "http://www.cnblogs.com/"; const string url2 = "http://www.cnblogs.com/atomy/"; //异步下载某网站内容,并统计字符的个数。 Task<int> t1 = CountCharactersAsync("url1", url1); Task<int> t2 = CountCharactersAsync("url2", url2); //主要是经过拼接字符串达到耗时操做 for (var i = 0; i < 3; i++) { ExtraOperation(i + 1); } //控制台输出 Console.WriteLine($"{url1} 的字符个数:{t1.Result}"); Console.WriteLine($"{url2} 的字符个数:{t2.Result}"); Console.WriteLine($"总耗时{stopwatch.ElapsedMilliseconds}ms。"); Console.Read(); #endregion } /// <summary> /// 统计字符个数 /// </summary> /// <param name="id"></param> /// <param name="address"></param> /// <returns></returns> private static async Task<int> CountCharactersAsync(string name, string address) { var wc = new WebClient(); Console.WriteLine($"{name}开始调用,历时{stopwatch.ElapsedMilliseconds}ms,线程id={Thread.CurrentThread.ManagedThreadId}。"); var result =await wc.DownloadStringTaskAsync(address); Console.WriteLine($"{name}调用完成,历时{stopwatch.ElapsedMilliseconds}ms,线程id={Thread.CurrentThread.ManagedThreadId}。"); return result.Length; } /// <summary> /// 额外操做 /// </summary> /// <param name="id"></param> private static void ExtraOperation(int id) { //这里是经过拼接字符串进行一些相对耗时的操做 var s = ""; for (var i = 0; i < 6000; i++) { s += i; } Console.WriteLine($"第{id}次ExtraOperation执行完成,历时:{stopwatch.ElapsedMilliseconds}ms。"); } }
运行结果以下:
三、async & await 结构
async & await结构可分红三部分:
1)调用方法:该方法调用异步方法,而后在异步方法执行其任务的时候继续执行;
2)异步方法:该方法异步执行工做,而后马上返回到调用方法;
3)await表达式:用于异步方法内部,指出须要异步执行的任务。一个异步方法能够包含多个await表达式(不存在 await 表达式的话IDE会发出警告)。
四、异步方法
异步方法:在执行完成前当即返回调用方法,在调用方法继续执行的过程当中完成任务。
语法分析:
参考自: