码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 【C#】async和await


    大概理解

    查了一个小时的资料:async和await

    发现这个大神的解释一针见血,深得我心!以最简单的例子,解释了async和await。妙~~~

    大多情况下,分开才能体现async和await的价值!

     但,await 并没有这么简单。

    深入分析

    await和Wait()的区别

    接下来继续往下看:

    await Task.Delay(3000);  和Task.Delay(3000).Wait();   有没有区别?

    上代码:

    1. using System.Diagnostics;
    2. namespace await_async2
    3. {
    4. internal class Program
    5. {
    6. static public void TestWait()
    7. {
    8. var t = Task.Factory.StartNew(() =>
    9. {
    10. Console.WriteLine("Start");
    11. Task.Delay(3000).Wait();
    12. Console.WriteLine("Done");
    13. });
    14. t.Wait();
    15. Console.WriteLine("All done");
    16. }
    17. static public void TestWait2()
    18. {
    19. var t = Task.Factory.StartNew(async () =>
    20. {
    21. Console.WriteLine("Start");
    22. await Task.Delay(3000);
    23. Console.WriteLine("Done");
    24. });
    25. t.Wait();
    26. Console.WriteLine("All done");
    27. }
    28. static public void TestWait3()
    29. {
    30. var t = Task.Run(async () =>
    31. {
    32. Console.WriteLine("Start");
    33. await Task.Delay(3000);
    34. Console.WriteLine("Done");
    35. });
    36. t.Wait();
    37. Console.WriteLine("All done");
    38. }
    39. static void Main(string[] args)
    40. {
    41. TestWait2();
    42. //避免程序提前退出,导致一些现象看不到
    43. Task.Delay(5000).Wait();
    44. }
    45. }
    46. }

    首先,强调一下,最后一句 Task.Delay(5000).Wait(); 是必须的,不然,程序提前退出,导致一些现象看不到,从而蒙蔽了我们。

    第1段代码TestWait执行效果,如下:

    第2段代码TestWait2执行效果,如下:

    第3段代码TestWait3执行效果,如下:

     现在给出结论:

    Task.Delay(3000).Wait(); 这个就是同步等。

    await Task.Delay(3000); 因为没有分开来写(见第一张图),所以基本和同步等没有区别。

    但是如果 await Task.Delay(3000); 是写到:Task.Factory.StartNew里面的

    1. static public void TestWait2()
    2. {
    3. var t = Task.Factory.StartNew(async () =>
    4. {
    5. Console.WriteLine("Start");
    6. await Task.Delay(3000);
    7. Console.WriteLine("Done");
    8. });
    9. t.Wait();
    10. Console.WriteLine("All done");
    11. }

    那这个效果不一样了,他们执行的权限丢出去了有点像python里的yeild,来看下程序的执行顺序:

     这里就看出了:await Task.Delay(3000);  和Task.Delay(3000).Wait(); 的区别了。(但是这种情况如果在道Task.Run里面就体现不出来!)

    然后,我有简单做了一个实验:

    这就更明了了, await Task.Delay(3000); 就像设置了一个回调,一旦三秒时间一到,程序的指针就会回到await Task.Delay(3000);后面的位置,直到函数执行结束。再回到之前的位置。这就是所谓的用同步的方式写异步的代码吧。

    但是,为啥在Task.Factory.StartNew才会体现出来,这个我就不清楚了,请各位大佬指点一下。

    去掉Task.Run的Wait

    再来对比一下,下面这两个函数:

    1. static public void TestWait8()
    2. {
    3. var t = Task.Run(async () =>
    4. {
    5. Console.WriteLine("Start");
    6. await Task.Delay(3000);
    7. Console.WriteLine("Done");
    8. });
    9. Console.WriteLine("All done");
    10. }
    11. static public void TestWait8_5()
    12. {
    13. var t = Task.Factory.StartNew(async () =>
    14. {
    15. Console.WriteLine("Start");
    16. await Task.Delay(3000);
    17. Console.WriteLine("Done");
    18. });
    19. t.Wait();
    20. Console.WriteLine("All done");
    21. }

    先看第一个TestWait8,由于Task.Run不再调用 t.Wait(),Task.Run内部这个线程和主线程是并行的关系。程序指针会在两个线程中来回切换。如果一方中写了await xxx,那程序指针必然跳到另一个线程。直达await结束才可能返回。 这种情形是比较多的。此时await能节省大量等待时间(比如IO操作时间),充分利用等待时间。

    此时 Console.WriteLine("All done");会最先被打印出来。

    再看第二个TestWait8_5(其实就是回顾一下),当程序执行到t.Wait()时,程序不会继续向下了,(此时因为有t.Wait()的存在,所以子线程其实是优先于主线程的)而是进入到子线程的内部进程,试图将这个线程执行完,但是再线程里面遇到又遇到await Task.Delay(3000);此时程序指针不会再这里死等,程序指针又跳回主线程继续执行,直到三秒到了之后就会回到子线程,子线程执行完了之后,再回到主线程。

    但是如果吧TestWait8_5 中    Task.Factory.StartNew 换成 Task.Run ,那么前面的过程一样,只是执行到await Task.Delay(3000);时候,此时会死等,不会跳到主线程,而是一定等到这个子线程完结,再回主线程。

    小结

    总结一下就是,遇到await 一定会等,至于程序指针是先跳到其他线程,还是在此线程死等,就看你的线程函数这么写的了。

    其他

    .Await();

    最后,还有个:Task.Delay(3000).Await();

    这个是prsim对Task写的的一个拓展方法(避免在主线程调用时,阻塞UI):

    2023年7月28日更新:

    这篇文章的坑已经填了,请看这篇:

    【C#】async和await 续_code bean的博客-CSDN博客在文章《async和await》中,我们观察到了一下客观的规律,但是没有讲到本质,而且还遗留了一个问题:这篇文章中,我们继续看看这个问题如何解决!当时问题是,为啥 Task.Factory.StartNew 可以看到异步效果,而Task.Run中却是同步效果。那其实是因为,Task.Factory.StartNew 返回的 t.Wait();它没卡住主线程,而Task.Run的 t.Wait();它卡住了。那为啥,Task.Factory.StartNew没卡住呢?https://blog.csdn.net/songhuangong123/article/details/131980699?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22131980699%22%2C%22source%22%3A%22songhuangong123%22%7D#:~:text=%E3%80%90C%23%E3%80%91-,async%E5%92%8Cawait%20%E7%BB%AD,-%E5%AE%A1%E6%A0%B8%E4%B8%AD

  • 相关阅读:
    Netty10-WebSocket长连接开发
    在uniapp中,如何去掉一些不想要的权限,
    显示命令行控制台(cmd.exe)的几种方式——Qt、C++
    一文整理深度学习【深度学习linux的docker+pytorch+cuda+nvidia-docker+vscode配置】
    Android 九宫格布局
    Cannot read properties of null bug解决方法
    Redis常用数据结构详解
    6种常见分布式唯一ID生成策略及它们的优缺点对比
    Android 自定义带动画的柱状图
    人工神经网络数学模型图,神经网络模型数学建模
  • 原文地址:https://blog.csdn.net/songhuangong123/article/details/127627231
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号