当前位置: 首页 > 编程日记 > 正文

await使用中的阻塞和并发(一)

好吧,不加点陈述不让发首页。那我们来陈述一下本篇提到的问题和对应的方法。

在.NET4.5中,我们可以配合使用async和await两个关键字,来以写同步代码的方式,实现异步的操作。

好处我目前看来有两点:

1.不会阻塞UI线程。一旦UI线程不能及时响应,会极大的影响用户体验,这点在手机和平板的APP上尤为重要。

2.代码简洁。

  • 相对基于event的异步方式,在多次回调的情况下(比如需要多次调web service,且后续调用基于前次调用的结果)特别明显。可以将多个+=Completed方法合并到一起。
  • 相对于Begin/End的异步方式,避免了N重且不能对齐的大括号。

在同一个方法里存在多个await的情况下,如后续Async方法无需等待之前的Aysnc方法返回的结果,会隐式的以并行方式来运行后面的Async方法。

值得注意的是错误的写法会导致非预期的阻塞,下文会以简单的例子来讨论在使用await的情况下,怎样实现多个Task的并发执行。

我们这里先看几个方法定义:

复制代码
        static async Task Delay3000Async(){await Task.Delay(3000);Console.WriteLine(3000);Console.WriteLine(DateTime.Now);}static async Task Delay2000Async(){await Task.Delay(2000);Console.WriteLine(2000);Console.WriteLine(DateTime.Now);}static async Task Delay1000Async(){await Task.Delay(1000);Console.WriteLine(1000);Console.WriteLine(DateTime.Now);}
复制代码

作用很简单,仅仅是起到延迟的作用。我们再来看如下写法的调用

复制代码
            Console.WriteLine(DateTime.Now);new Action(async () =>{await Delay3000Async();await Delay2000Async();await Delay1000Async();})();        
复制代码

结果如图,可以看出3个await是线性执行,第一个await会返回并阻止接下来的await后面的方法。这应该不是我们想要的效果,毕竟后面的方法并不依赖第一个方法的执行。

我们换一种写法,再运行一次程序:

复制代码
            var task3 = Delay3000Async();var task2 = Delay2000Async();var task1 = Delay1000Async();new Action(async () =>{await task3;await task2;await task1;})();    
复制代码

可以看到3个await后面的方法是并行执行的。MSDN的解释如下:

In an async method, tasks are started when they’re created. The Await (Visual Basic) or await (C#) operator is applied to the task at the point in the method where processing can’t continue until the task finishes. 

However, you can separate creating the task from awaiting the task if your program has other work to accomplish that doesn’t depend on the completion of the task.

Between starting a task and awaiting it, you can start other tasks. The additional tasks implicitly run in parallel, but no additional threads are created.

MSDN原文传送门

到这里并没有结束 ,后面还有一些奇怪的事情:

复制代码
            var tasks = new List<Task>{Delay3000Async(),Delay2000Async(),Delay1000Async()};tasks.ForEach(async _ => await _);
复制代码

这个结果和上面是一样的,可以并行执行。这并不奇怪,我们仅仅是把Task放到一个List里,按照MSDN的说法,Task在被我们放进List时就被创建,且并发执行了。

那么我们再来一个List,这回放进去的不是Task,而是Func<Task>:

复制代码
            var funcList = new List<Func<Task>>(){Delay3000Async,Delay2000Async,Delay1000Async};funcList.ForEach(async _ => await _());
复制代码

仍然可以并发执行,看上去似乎没什么问题,但是作为Func<Task>来存储到List里,应该是没有被创建出来才对。为什么会能够并发呢?

我们再来看最后一组写法:

复制代码
            Func<Task> func3 = Delay3000Async;Func<Task> func2 = Delay2000Async;Func<Task> func1 = Delay1000Async;new Action(async () =>{await func3();await func2();await func1();})();
复制代码

意料之中的,以上的写法并不能够做到并发执行。而是需要按顺序执行func3,func2和func1。这很好解释,因为: a task is awaited as soon as it’s created。我们在创建Task之后立即就要求阻塞并等待完成才进行下一步。

写到这里的时候对List<Func<Task>>的例子开始迷糊了。参考了Reflector反编译的结果……我想说……没看出来有什么区别……本篇先到这里。一旦琢磨出个所以然,我再发第二篇好了。

还恭请各位高人不吝赐教,多多提点。

补充:对List<Func<Task>>的那个例子,我怀疑是Foreach这个扩展方法在偷偷做了优化。故增加了如下的试验:

复制代码
       static async Task TestForeach(){var funcList = new List<Func<Task>>(){Delay3000Async,Delay2000Async,Delay1000Async};foreach (var item in funcList){
          //这里干了件蠢事,不要主动阻塞在这里,就可以并发了……await item();}}
复制代码

试验结果表明用foreach来写的话,确实是做不到并行执行的。那么就需要去看一下Foreach的背后到底发生了什么。我还要研究研究才能写下一篇……

哈哈哈哈,干了件蠢事情……

转载于:https://www.cnblogs.com/leo9527/p/10340699.html

相关文章:

中国经济是前所未有二元经济(转)

今天的中国是一个前所未有的二元经济&#xff0c;而且是三七开的二元经济&#xff0c;我国这么多年的经济发展&#xff0c;每一年GDP以10%的成长率增长的原因&#xff0c;就是二元经济的过热部门推动的&#xff0c;因此我们GDP的组成是非常扭曲的&#xff0c;超过一半都是固定资…

Unity 简单示例代码和向导/Unity Aplication Block

Unity 简单示例代码和向导 关于Unity 的说明和下载地址&#xff0c;请访问[微软控制反转和依赖注入容器Unity 1.0发布] http://forum.entlib.com/Default.aspx?gposts&t25 。 下面的范例主要实现&#xff1a;首先&#xff0c;定义ILogger 接口。然后&#xff0c;定义一个实…

crontab修改默认编辑器

$ sudo select-editor 选择3或者4 然后再次打开 crontab -e 就会是vim的方式了。 转载于:https://www.cnblogs.com/jiqing9006/p/10343035.html

Programming C# 学习笔记(二) 出发:“Hello World”

小序&#xff1a; 准备写这章的学习笔记了&#xff0c;啊&#xff0c;Hello World&#xff01;多么亲切的语句&#xff0c;呵呵&#xff0c;当初学C语言的第一个程序就是输出它&#xff0c; 还记得费了好大劲终于把它输出来时候的那种兴奋感觉&#xff0c;真是让我怀念哦&a…

多IP绑定与多网卡绑定

多IP绑定&#xff1a; 实验目的&#xff1a; 实现如下图网络连接 实现 A, B 在分配不同网段的网络地址的情况下可以互联 实验条件有限&#xff0c;在没有交换机的情况下&#xff0c;将主机A &#xff0c;B&#xff0c;路由器R1处于同一网络。将三台虚拟机的网络适配器设置为仅主…

华硕WL-500W无线路由器使用感受

作为一款实用型的家庭或小型企业应用的无线路由器&#xff0c;WL-500W有着独特的外观&#xff1a;<?xml:namespace prefix v ns "urn:schemas-microsoft-com:vml" /><?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office"…

什么是物联网网关?物联网网关具备什么功能?_转

参考&#xff1a;什么是物联网&#xff1f;物联网产业链体系深度分析 随着物联网概念的不断深入&#xff0c;商业级的网络应用遍地开花&#xff0c;各种智能家电层出不穷&#xff0c;改善着我们的生活。与此同时&#xff0c;物联网网关也将成为连接的重要纽带。作为网关设备&am…

MSDN Webcast“深入浅出ASP.NET AJAX系列”

课程&#xff1a; ASP.NET AJAX深入浅出系列课程(1)&#xff1a;ASP.NET AJAX 概述&#xff08;3月13日&#xff09;&#xff1a;对于ASP.NET AJAX的大致功能进行概述和演示&#xff0c;通过简单的演示让听众了解到ASP.NET AJAX框架的强大之处&#xff0c;以及对于开发带来的便…

技巧:结合Zabbix与SNMP监控嵌入式设备

在如何利用Zabbix监控网络设备三篇文章的前两篇中&#xff0c;我们介绍了如何通过Zabbix代理监控网络设备。但有些设备无法安装Zabbix代理&#xff0c;需要采用其他方法监控。需要考虑无法安装软件的嵌入式设备或应用程序。对于这些设备&#xff0c;可通过SNMP进行监控。    …

值得收藏的146条经典民间偏方

1、本贴所用药物&#xff0c;以食物为主&#xff0c;绝对无毒。 2、为使读者易懂&#xff0c;剂量单位均用旧制&#xff0c;如&#xff1a;斤、两、钱等&#xff0c;有的用碗&#xff0c;是指一般性中碗。 3、所用药物凡带有*记号的一般可到中药店买&#xff0c;药店都有。 4、…

DataGridView打印类

一下这个类专门用于打印DataGridView,但是功能不是很强大 如果有个性化需求 可在此基础上简单修改 Code 1public class DataGridViewPrint 2 { 3 private DataGridView dataGridView; 4 private PrintDocument printDocument; 5 private PageSetu…

Asp.Net Core AsyncLocal 异步上下文

引子 阅读以下代码&#xff0c;并尝试分析 代码解析 在主线程中&#xff0c;线程Id为1&#xff0c;为线程变量赋值 变量d6ff开启一个新的task&#xff0c;此时线程Id为4&#xff0c;变量d6ff&#xff0c;并调用Task1开启一个同步Task3&#xff0c;线程Id为1。变量d6ff&#xff…

JDBC数据库操作

启动MySQL数据库服务 网络课堂中共享的MySQL 5.1压缩包下载后&#xff0c;直接在C盘根目录下解压后&#xff0c; 进入bin目录&#xff0c;执行“启动服务.cmd”即可启动服务器&#xff08;如果未放在C盘根目 录下&#xff0c;需要修改配置文件my.ini和启动服务.cmd&#xff09…

mybatis学习7 实战项目

自己写一个实战项目&#xff0c;最好和hibernate做对比。转载于:https://www.cnblogs.com/liufei1983/p/7492214.html

凤凰网制作的 “中国挺住” 桌面与MSN,QQ头像下载

凤凰网制作的 “中国挺住” 桌面与MSN&#xff0c;QQ头像下载。 点击下载 转载于:https://www.cnblogs.com/yajiya/archive/2008/05/24/1206574.html

树莓派Android Things物联网开发:创建一个Things项目

【转载请注明出处: http://blog.csdn.net/leytton/article/details/77854144】《树莓派Android Things物联网开发》系列文章专栏 http://blog.csdn.net/column/details/17741.html树莓派Android Things物联网开发&#xff1a;入门及资料汇总树莓派Android Things物联网开发&…

使用JDBC进行MySQL 5.1的数据连接、查询、修改等操作练习。

目录 顺序查找 控制游标 条件与排序查询 1. where子语句 一般格式&#xff1a; 2. 排序 更新、添加与删除操作 1.更新 2.添加 3.删除 通用查询 顺序查找 所谓顺序查询&#xff0c;是指ResultSet对象一次只能看到一个数据行&#xff0c;使用 next()方法移到下一个数据行…

Tensorflow多线程输入数据处理框架(一)——队列与多线程

参考书 《TensorFlow&#xff1a;实战Google深度学习框架》&#xff08;第2版&#xff09; 对于队列&#xff0c;修改队列状态的操作主要有Enqueue、EnqueueMany和Dequeue。以下程序展示了如何使用这些函数来操作一个队列。 #!/usr/bin/env python # -*- coding: UTF-8 -*- # c…

编译器错误信息: CS0016

编译器错误信息: CS0016: 未能写入输出文件,..\Temporary ASP.NET Files\WebApp\d087da43\c12930d8\9ze28k_8.dll”--拒绝访问 编译器错误信息: CS0016: 未能写入输出文件“d:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\Temporary ASP.NET Files\5177u\d087da43\c12930d8\9ze…

Visual Studio 2008 Samples Page

Visual Studio 2008 Samples Page http://msdn.microsoft.com/zh-cn/bb330936(en-us).aspx 如何实现 - 常规开发http://msdn.microsoft.com/zh-cn/library/ms246578.aspx Visual Studio 2008http://msdn.microsoft.com/zh-cn/library/aa187917.aspx .NET Framework 3.5http://m…

iOS开发网络篇—HTTP协议

说明&#xff1a;apache tomcat服务器必须占用8080端口 一、URL 1.基本介绍 URL的全称是Uniform Resource Locator&#xff08;统一资源定位符&#xff09; 通过1个URL&#xff0c;能找到互联网上唯一的1个资源 URL就是资源的地址、位置&#xff0c;互联网上的每个资源都有一个…

操作系统导论部分章节习题

进程 一。单选题&#xff08;共1题&#xff0c;10.0分&#xff09; 当某个进程进行系统调用以通过网络传输TCP数据包时&#xff0c;以下哪些步骤不会总是发生&#xff1f; A进程进入内核模式。 B&#xff0c;CPU的程序计数器转移到地址空间的内核部分。 C&#xff0c;该进…

Go-技篇第一 技巧杂烩

Go-技篇第一 技巧杂烩一句话技巧把你面向对象的大脑扔到家里吧&#xff0c;去拥抱接口。mikegehard学习如何使用Go的方式做事&#xff0c;不要把别的的编程风格强行用在Go里面。DrNic多用接口总比少用好。evanphx拥抱这种简洁、并行、工整的语言。francesc阅读官网golang.org上…

Visual Studio 2008 到底有多强?漫画告诉你 !

插入数据需要无数个SQL语句支持&#xff0c;而现在&#xff0c;你只需要有一个强大的LinQ巴士&#xff0c;就直接一次性全搞定&#xff0c;方便快捷 " 强大的中转站&#xff0c;帮你解决额外的问题&#xff0c;数据传输选择最优路径&#xff0c;完成工作。数据给了WCF&a…

使用c#生成高品质小空间的缩略图

dot自带的生成缩略图的方法是Bitmap.GetThumbnailImage这个方法生成的缩略图不够清晰&#xff0c;一般我们会使用Graphics高质量插值发生成清晰的缩略图&#xff0c;这时候大小会不尽人意&#xff0c;怎么办&#xff1f;我们可以使用jpeg压缩的方法压缩一下图片&#xff0c;这样…

将Project的内容导出成单独的XPO文件

AX跟VSS整合的版本管理可以通过创建知识库将当前层的代码全部签入到VSS中&#xff0c;但是如果不是一个团队开发solution&#xff0c;而是针对客户的需求随时做得一些小改动&#xff0c;一般都希望以Project的形式组织代码和发布代码。AX与VSS的整合没有提供一种方法可以将一个…

.Net Core MVC初学习

.net core已经出来很长一段时间了&#xff0c;没有很好的学习过&#xff0c;现在工作不那么忙了&#xff0c;参考官方文档&#xff0c;在这里记录自己的学习过程&#xff01; ASP.NET Core 是一个跨平台的高性能开源框架&#xff0c;用于生成基于云且连接 Internet 的新式应用程…

编译原理考点复习

名词填空、名词解释、解答题&#xff1a; 文法是什么&#xff1f;文法、句子、句型、确定有穷自动机&#xff08;DFA&#xff09;、非确定有穷自动机&#xff08;NFA&#xff09;的定义&#xff1f;编译过程主要有哪些功能模块&#xff1f;有什么辅助模块&#xff08;表格管理…

网络工程师如何才能实现职位晋升

一、如何在公司得到攀升的机会&#xff1f;如果不想保持低月薪&#xff0c;就运用你的技术积极参与公司的业务发展从最近我们公司招生来看&#xff0c;一个很明显的问题阴魂不散的笼罩在“网络工程师”这个行业。问题的根本是对网络工程师职业前途的严重误解。很多人认为目前的…

Linux中/etc/resolv.conf文件简析

https://blog.csdn.net/lcr_happy/article/details/54867510转载于:https://www.cnblogs.com/answercard/p/10354514.html