c# 关于async/await异步编程的浅析和使用

线程的同步运行,时效性慢,异步运行,时效性快!

在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();
        }

执行结果:

原文地址:https://www.cnblogs.com/williamwsj/p/8526749.html