线程的同步运行,时效性慢,异步运行,时效性快!
在c#5.0引出了async/await关键字,可以用其来进行异步编程。
async/await定义异步方法的语法如下:
1、在方法的返回类型前面加上async关键字;
2、返回类型固定为void、Task和Task<T>。返回类型建议用Task或Task<T>,因为void不方便捕获异常;
3、形参不能使用out和ref关键字;
4、在方法体内,需要包含1到多个await表达式,每一个表示需要异步执行的任务;
5、方法名的后缀一般约定加上Async。
//返回Task的异步方法示例: public static async Task DownLoadDataAsync() { var wc = new WebClient(); var result = await wc.DownloadStringTaskAsync(@"http://www.baidu.com"); } //返回Task<T>的异步方法示例: public static async Task<String> DownLoadDataAsync() { var wc = new WebClient(); var result = await wc.DownloadStringTaskAsync(@"http://www.baidu.com"); return result; }
备注:Task关键字表示任务调度,一般以异步的方式执行。如果async异步方法需要返回数据,则其返回类型使用Task<T>的方式,类型T就是真正需要返回的参数类型,而异步方法执行完毕后会将需要返回的参数存储在Task变量中。
说到异步执行,到底在哪一步才进行了异步执行?这就引出了await关键字。请看下面的代码:
class Program { static void Main(string[] args) { Task<String> task = DownLoadDataAsync(); Console.WriteLine("这是main主线程!"); Console.ReadKey(); } //返回Task<T>的异步方法示例: public static async Task<String> DownLoadDataAsync() { Console.WriteLine("进入异步方法第一步!"); var wc = new WebClient(); Console.WriteLine("进入异步方法第二步!"); var result = await wc.DownloadStringTaskAsync(@"http://www.baidu.com"); Console.WriteLine("进入异步方法第三步!"); return result; } }
执行结果:
可以看见,在执行异步方法的时候,当程序执行到await时,就开始了异步执行!为何能够异步呢?接下来再测试一下。
static void Main(string[] args) { Console.WriteLine($"1.main tid:{Thread.CurrentThread.ManagedThreadId}"); DelayAsync(); Console.WriteLine($"2.main tid:{Thread.CurrentThread.ManagedThreadId}"); Console.ReadKey(); } private static async Task DelayAsync() { Console.WriteLine($"1.DelayAsync tid:{Thread.CurrentThread.ManagedThreadId}"); await Task.Delay(1).ContinueWith(t => { Console.WriteLine($"2.DelayAsync tid:{Thread.CurrentThread.ManagedThreadId}"); }); Console.WriteLine($"3.DelayAsync tid:{Thread.CurrentThread.ManagedThreadId}"); await Task.Delay(1).ContinueWith(t => { Console.WriteLine($"4.DelayAsync tid:{Thread.CurrentThread.ManagedThreadId}"); }); Console.WriteLine($"5.DelayAsync tid:{Thread.CurrentThread.ManagedThreadId}"); }
程序执行结果:
原来是到了await这个关键字时,程序单独开辟了一个线程去执行await后的代码,而后执行步骤直接返回到主线程调用异步方法后一步!
如何在main主线程执行完毕之前获取异步方法的返回结果?这就要用到Task的Wait()方法!
Task.Wait()方法的功能是等待当前这个异步任务执行完毕。相当于阻塞了主线程的继续执行,直到异步方法执行完毕,主线程才可继续执行。这就是为何异步方法的返回类型为Task的原因!
static void Main(string[] args) { Task<String> task = DownLoadDataAsync(); task.Wait(); Console.WriteLine("这是main主线程!"); Console.ReadKey(); }
执行结果: