C#进阶之Async await异步编程

作者: LuyaoCore | 来源:发表于2019-07-31 22:11 被阅读0次

    前言

    自从C# 5.0时代引入async和await关键字后,异步编程就变得流行起来。尤其在现在的.NET Core时代,甚至如果你的代码中没有出现async或者await关键字,都会让人感觉到很奇怪。
    本篇文章将会先给大家带来一个关于Async简单的例子,然后再四种启动线程的方法的对比中让大家意识到为什么现在的大佬都偏爱Async await.
    在这之前,我希望大家首先能知道下面这个事实:

    // < : 后者性能高于前者
    Thread < ThreadPoll < Task < Async await

    Async await

    方法使用Async修饰符修饰.
    返回类型仅有三种: void,Task,Task<T>
    方法内部使用await关键字标明开始执行异步代码
    await标志前的代码是同步执行,await标志的方法是异步执行,await标志的方法后面的代码相当于"回调函数",在await标志的异步方法后面执行.
    所以使用Async await异步编程之后代码的执行顺序会变成下面这样:


    Async await编程代码执行顺序.png

    如果没看懂上图,也没关系,我们再来看一个小例子:
    下面个例子中,我用英文的输出代表主线程的输出,中文的输出代表子线程的输出

        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("Let`s Do This!");
                Console.WriteLine("I am going to call my son.");
                AsyncTask();//调用Async修饰的方法
                Console.WriteLine("My son is busy now,and I will go on.");
                Console.WriteLine("I`m done!");
                Console.ReadLine();
            }
    
           //Async修饰的方法
            public async Task AsyncTask()
            {
                Console.WriteLine($"我是方法AsyncTask");
                var result= await WasteTime();
                Console.WriteLine(result);
                Console.WriteLine("我已经干完了我应该干的事情!");
            }
    
            private async Task<string> WasteTime()
            {
                return await Task.Run(() =>
                {
                    Thread.Sleep(1);//避免Console.WriteLine执行太快使整个程序执行起来像是同步执行的
                    Console.WriteLine("我开始异步执行了!");
                    Console.WriteLine("可是我啥都不想干,还是等个五秒钟就跟主线程说我做好了吧");
                    Thread.Sleep(5000);
                    return "我异步执行完了";
                });
            }
        }
    

    运行效果如下:


    运行效果.png

    为什么Thread < ThreadPoll

    Thread创建的是后台线程,每次初始化一个Thread的示例,就会创建一个新的线程!
    ThreadPoll创建的是前台线程,每次启动线程,每次启用线程会从线程池寻找空闲的线程,如果找到了,就会调用这个空闲的线程,而不是直接创建一个新的的线程.
    而每次创建一个线程,起码约消耗1M的内存.
    因此,相比于Thread,ThreadPoll具有减少开启新线程消耗的资源,以及统一管理线程的优势!

    为什么ThreadPoll < Task

    ThreadPool使用的是线程池全局队列,全局队列中的线程依旧会存在竞争共享资源的情况,从而影响性能。
    Task基于ThreadPool实现,相当于ThreadPoll的优化版.它不再使用线程池的全局队列,而是使用的本地队列,使线程之间的资源竞争减少。同时Task提供了丰富的API来管理线程、控制。但是相对前面的两种耗内存,Task依赖于CPU对于多核的CPU性能远超前两者,单核的CPU三者的性能没什么差别。

    为什么Task < Async await

    1.举个例子:
    现在需要实现一个,异步写数据库,写成功之后需要在页面上弹出一个小窗提示.
    如果你用task.result来实现的话,那么在获取到结果之前,task会使你的项目进去一个阻塞状态.也就是说在小窗弹出来之前,你的程序会一直卡主!从而形成异步编程中的同步阻塞
    而Async await则不会发生这种情况.你需要做的仅仅只是在await修饰的方法后面调一个弹出小窗的方法而已.也就是传说中的异步阻塞

    2.Async await风格的编程会使代码看起来更像是同步代码,也就更像清新移动更通俗.

    结语

    其实在你理解了异步编程的基础上,Async await并没有什么复杂的.明白了例子中带返回值的写法,那别的两种返回类型应该也是信手拈来.从表面上看来,它的编码风格跟同步方法非常相似,以至于新手看到会有一种"我*,这不是同步方法吗"的感觉,从而给心理上造成了一定负担,使自己觉得Async很难,所以懒得去研究了.

    最后,如果本篇文章给您带来了帮助,就点个赞再走呗~

    相关文章

      网友评论

        本文标题:C#进阶之Async await异步编程

        本文链接:https://www.haomeiwen.com/subject/xkkxdctx.html