zoukankan      html  css  js  c++  java
  • 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();
            }

    执行结果:

  • 相关阅读:
    一个完整的SQL SERVER数据库全文索引的示例
    sqlhelper for access
    解决打开网站弹出下载文件
    18句话入门SQLServer XML
    c# winform 自动关闭messagebox 模拟回车
    jquery json
    用超级巡警批量清除被挂马的网页
    sqlhelper for sql
    SQL XML DML 数据修改
    post方法易错地方
  • 原文地址:https://www.cnblogs.com/williamwsj/p/8526749.html
Copyright © 2011-2022 走看看