惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
D
Docker
Microsoft Security Blog
Microsoft Security Blog
Google DeepMind News
Google DeepMind News
M
MIT News - Artificial intelligence
P
Proofpoint News Feed
Engineering at Meta
Engineering at Meta
Y
Y Combinator Blog
Vercel News
Vercel News
F
Fortinet All Blogs
B
Blog
Recent Announcements
Recent Announcements
A
About on SuperTechFans
GbyAI
GbyAI
T
The Blog of Author Tim Ferriss
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - Franky
MongoDB | Blog
MongoDB | Blog
Stack Overflow Blog
Stack Overflow Blog
B
Blog RSS Feed
C
Check Point Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
V
Visual Studio Blog
月光博客
月光博客

博客园 - 幸福的菜菜

windows下使用ACME申请SSL证书的办法 ElementPlus Radio 实现双击取消选择的效果 Windows10 LTSC版本 无法访问网络中部分的共享文件夹 SqlSugar : date绑定到XX失败,可以试着换一个类型,或者使用ORM自定义类型实现 VisualStudio Debug模式突然变慢 Visual Stadio 编译提示 The BaseOutputPath/OutputPath property is not set for project ... winform绘图与前端canvas绘图效率对比 node-sass编译不通过, 提示 “checking for Python executable "python2" in the PATH” winform 实现对usb热拔插的监听 Laravel The only supported ciphers are AES-128-CBC and AES-256-CBC with the correct key lengths Wampserver 配置端口可访问服务 git credential for windows 总是弹出的问题 如何用B表的数据,更新A表的值 WampServer部署https 服务的过程 PHP 命名空间冲突解决方式 Windows下 Docker 简单部署 Django应用 C#实现后台格式化U盘的功能 Winform 实现断点续传的思路及代码 WAMPServer ServerName has syntax error 的问题(阿里云服务器上)
c# async await的使用方式及为啥要用它
幸福的菜菜 · 2022-01-21 · via 博客园 - 幸福的菜菜

c# 5的语法(.net framework 4.5+ 版本)引入了 async await的概念,再加上前端开发也经常出现这个概念。用的少,理解也不深,看到了一篇很容易入门的文章,所以在此写一些自己的理解:

本文来源于知乎的一篇文章,但是添加了一些自己的测试代码。知乎文章的链接如下

https://zhuanlan.zhihu.com/p/138805565

先来看一下顺序执行的例子

        internal static void Test()
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            Task task = new Task(CallMethod);
            //Task task = new Task(CallMethodAsync);
            task.Start();
            task.Wait();


            sw.Stop();
            Console.WriteLine("程序运行共 耗时:" + sw.ElapsedMilliseconds);
            Console.ReadLine();
        }

        static async void CallMethod()
        {
            Console.WriteLine(" Other Work 1111");
            string filePath = "d:\\sampleFile.txt";
            int a = ReadFile(filePath);

            Console.WriteLine(" Other Work 1");
            Thread.Sleep(1000);
            Console.WriteLine(" Other Work 2");
            Thread.Sleep(1000);
            Console.WriteLine(" Other Work 3");

            int length = a;
            Console.WriteLine(" Total length: " + length);

            Console.WriteLine(" After work 1");
            Console.WriteLine(" After work 2");
        }


        static int ReadFile(string file)
        {
            int length = 0;

            Console.WriteLine(" File reading is stating");
            using (StreamReader reader = new StreamReader(file))
            {
                // Reads all characters from the current position to the end of the stream asynchronously   
                // and returns them as one string.   
                string s = reader.ReadToEnd();

                length = s.Length;
            }
            Thread.Sleep(2000);
            //Console.WriteLine("Hello world");
            Console.WriteLine(" File reading is completed");
            return length;
        }

程序执行以后,输出如下:

 

可以看到,因为我在ReadFile 里面进行了延时,所以ReadFile内的函数耗时 + 函数外的耗时  = 4秒 左右

再看一下使用async await异步执行的例子

        internal static void Test()
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            //Task task = new Task(CallMethod);
            Task task = new Task(CallMethodAsync);
            task.Start();
            task.Wait();


            sw.Stop();
            Console.WriteLine("程序运行共 耗时:" + sw.ElapsedMilliseconds);
            Console.ReadLine();
        }

        static async void CallMethodAsync()
        {
            Console.WriteLine(" Other Work 1111");
            string filePath = "d:\\sampleFile.txt";
            Task<int> task = ReadFileAsync(filePath);

            Console.WriteLine(" Other Work 1");
            Thread.Sleep(1000);
            Console.WriteLine(" Other Work 2");
            Thread.Sleep(1000);
            Console.WriteLine(" Other Work 3");

            int length = await task;
            Console.WriteLine(" Total length: " + length);

            Console.WriteLine(" After work 1");
            Console.WriteLine(" After work 2");
        }


        static async Task<int> ReadFileAsync(string file)
        {
            int length = 0;

            Console.WriteLine(" File reading is stating");
            using (StreamReader reader = new StreamReader(file))
            {
                // Reads all characters from the current position to the end of the stream asynchronously   
                // and returns them as one string.   
                string s = await reader.ReadToEndAsync();

                length = s.Length;
            }
            Thread.Sleep(2000);
            Console.WriteLine(" File reading is completed");
            return length;
        }

程序输出的结果如下:

 可以看到,使用 async await 的异步执行,只花费了2秒左右的时间。

这是为什么呢? 因为使用异步执行时,函数内部已经开启独立的Task 去执行了。所以函数主体依然能够一直运行,直至

这一步的时候,因为内外层都是2秒左右的延时,所以无需等待时间,极大地缩短了运行时间。

如果我们把 ReadFileAsync 的Sleep时间修改成三秒会发现输出更有意思了

 咦? 这里2秒,程序都跑完了,怎么才输出 Total length 以及结束的内容呢?这里就是异步编程的强大之处

如果使用传统的编程,那么这里 2 + 3 =5  秒程序才会结束

而如果使用异步编辑, 2< 3  = 3 秒程序实际就可以结束

这样子相比传统顺序执行的编程,那岂不是会有一个问题?函数主体都已经返回了,我却拿不到返回值,这咋整?

其实在ReadFile里面已经提供了范例: 如果要等  CallMethodAsync 的所有异步都结束再退出,可以将CallMethodAsync 改为 ReadFileAsync 的形式,在外层调用

修改之后得到的输出为:

如果不使用以上的方式,使用传统的编程方式,如何才能缩短执行时间呢?目前我是没想到更好,更优雅的方式……