1、async/await特性结构 异步方法:就是在处理完成之前就返回到调用方法。 async/await特性结构由三个部分构成: (1)调用方法:调用异步方法的那个方法,它和异步方法可能在相同的线程,也可能在不同的线程。在异步方法执行其任务的时候继续执行。 class Program {static void Main(){……Task<int> value=DoAsyncStuff.CalculateSumAsync(5,6);……} } (2) 异步方法:有异步标识 async static class DoAsyncStuff { public static async Task<int> CalculateSumAsync(int i1,int i2) ----这就是异步方法 有异步标识 async{int sum=await TaskEx.Run( () => GetSum(i1,i2));return sum;}…… } (3) await 表达式:异步方法内部,指明需要异步执行的任务。一个异步方法至少包含一个await表达式。 2 什么是异步方法 (1)异步方法 async关键字 至少一个await表达式 返回类型:void Task Task<T> 参数不能为out或ref参数 除了方法以外,Lambda表达式和匿名方法也可以作为异步对象。 Task<T>: 如果调用方法要获取一个T类型的值,异步方法的返回类型就必须是Task<T>.调用方法将通过读取Task的Result属性来获取这个T类型的值。这个是有返回参数的返回类型 例如: Task<int> value=DoStuff.CalculateSumAsync(5,6); …… Console.WriteLine("Value : {0}",value.Result); Task: 如果调用方法不需要从异步方法中返回某个值,但需要检查异步方法的状态,那么异步方法可以返回一个Task类型的对象。这时,即使异步方法出现了return语句,也不返回任何东西。例如: Task someTask=DoStuff.CalculateSumAsync(5,6); …… somTask.Wait(); Void:如果调用方法仅仅想执行异步方法,而不需要与它做任何进一步的交互时[这成为[fire and forget]。这时,与上面一样,即使方法中包含return语句也不会返回任何东西。Demo:使用返回Task<int> 对象的异步方法classProgram{staticvoid Main(string[] args){Task<int> value=DoAsyncStuff.CalculateSumAsync(5,6);Console.WriteLine("Value:{0}", value.Result);}}static async Task<int> CalculateSumAsync(int i1, int i2){int sum = awaitTask.Run(() => GetSum(i1, i2));return sum;} privatestaticint GetSum(int i1, int i2){return i1 + i2;} Demo:使用返回Task对象的异步方法classProgram{staticvoid Main(string[] args){Task someTask = DoAsyncStuff.CalculateSumAsync1(5, 6);//处理其他事情 someTask.Wait();Console.WriteLine("Async stuff is done");Console.ReadLine();}} publicstaticasyncTask CalculateSumAsync1(int i1, int i2){int sum = awaitTask.Run(() => GetSum(i1, i2));Console.WriteLine("Value:{0}", sum);}privatestaticint GetSum(int i1, int i2){ return i1 + i2;} Demo:使用返回void的异步方法staticvoid Main(string[] args){DoAsyncStuff.CalculateSumAsync2(5, 6);//处理其他事情Thread.Sleep(200);----如果这里不暂停当前线程,则会先输出Program Exiting,在输出11Console.WriteLine("Program Exiting");}publicstaticasyncvoid CalculateSumAsync2(int i1, int i2){int sum = awaitTask.Run(() => GetSum(i1, i2));Console.WriteLine("Value:{0}", sum);} privatestaticint GetSum(int i1, int i2){return i1 + i2; }当程序运行到异步方法内部的await表达式时,异步方法会立即创建一个返回类型Task或Task<T>的对象,并返回给调用方法。 调用方法使用Task对象,取其Result属性时,如果异步方法还没有设置该属性,调用方法就暂停等待。(2)异步方法控制流:privateasyncTask<int> CountCharactersAsync(string uriString){WebClient wc = newWebClient();string result = await wc.DownloadStringTaskAsync(uriString);return result.Length;} 上面的异步方法,在遇到await时会立即返回,返回的这个类型与await表达式本身的内容没有关系,会创建一个异步方法返回类型的对象,即Task<int>对象。而异步方法的return语句并没有真正返回某个值,只是退出了。 (3)await表达式 .net 4.5,有大量的异步方法在BCL中。比如上面的DownloadStringTaskAsync方法等。 也可以自己编写异步方法: 使用Task.Run()方法,这个方法是在不同的线程上运行你的方法。 Task.Run的签名:Task Run(Func<TReturn> func) 因此定义异步方法,最重要的就是要创建一个委托。 Demo:使用Task.Run定义await表达式,进而定义异步方法。classMyClass{publicint Get10(){ return 10; }publicasyncTask DoWorkAsync(){Func<int> ten = newFunc<int>(Get10);int a = awaitTask.Run(ten);int b = awaitTask.Run(newFunc<int>(Get10));int c = awaitTask.Run(() => { return 10; });//该Lambda表达式是与Func<int>兼容的将隐式转换为该委托Console.WriteLine("{0} {1} {2}", a, b, c);}}staticvoid Main(string[] args){Task t = (newMyClass()).DoWorkAsync();Console.WriteLine("111");t.Wait();Console.WriteLine("222");} 结果:Task.Run:
(4)取消一个异步操作(5)异常处理与await表达式 Task t t.Satus t.IsFaulted (6)在调用方法中同步的等待任务 wait() t.Wait(); Task.WaitAll(); Task.WaitAny();(7)在异步方法中异步的等待任务异步等待所有tasks中的任务完成,不会占用主线程的时间。