【憩园】C#并发编程之异步编程(一)
写在前面
C#5.0中,对异步编程进行了一次革命性的重构,引入了async和await这两个关键字,使得开发人员在不需要深刻了解异步编程的底层原理,就可以写出十分优美而又代码量极少的代码。如果使用得当,你可以写出具有并行化并且性能较高的程序,但是同时也增加了对异步编程理解的复杂度,毕竟在C#5.0里,你已经看不到异步编程具体是如何实现的了,需要花费额外的经历去研究探索。
使用异步编程,使得我们释放了启动它的线程,也使得资源的占有量下降。更重要的是,有些特殊线程,比如UI线程,在运行的时候只能启动一个,如果没有快速响应,页面将会出现卡顿现象。本文只会基于.NET FX4.5及以后的版本进行讲解,之前的版本如果要实现异步编程,需要从nuget上面下载Microsoft.Bcl.Async,不过我还是建议你,如果想要在系统中大量使用编写异步代码,还是要是使用.NET FX4.5或更高的版本
异步编程主要分为基于事件的异步模式(EAP)和基于任务的编程模式(TAP)。EAP在调用方法之前立即注册事件,它具有void返回类型,但这种模式比较混乱,它将原本的一个方法分拆成两个方法。本系列主要关注TAP编程而不涉及EAP编程。
异步编程是什么
异步关键字
作为C#5.0中新增的重量级功能,异步功能是指程序在进行长时间操作完成后,需要继续执行的操作的一种方法,在编程过程中,会感觉这些异步代码和同步或者阻塞代码类似,但是实际上,编译器会将标识为异步的方法进行进一步的转换,是的代码可以实现真正的异步编程。它主要以两个关键字的形式功能大家使用:
- async
- await
以下以一个通过EF Core查询用户信息的代码片段,这个例子没有什么特殊的地方
public Users GetUserInfo(string userId)
{
using (UserDbContext db = new UserDbContext())
{
var user = db.Users.FirstOrDefault(p => p.UserId = userId);
return user;
}
}
接下来我们看看异步的实现代码
public async Task<Users> GetUserInfoAsync(string userId)
{
using (UserDbContext db = new UserDbContext())
{
var user = await db.Users.FirstOrDefaultAsync(p => p.UserId = userId);
return user;
}
}
以上两段代码看起来非常的类似,但是仔细看却有明显的不同。异步方法上多了一个async的标识,同时返回值User,被标识成了Task<Users>,同时在进行数据库查询的时候,使用到了await。这里提前说一下await关键字,当编译器看到await关键字的时候,会截断方法,便于线程调度。简单点说,就是当调用线程运行到FirstOrDefaultAsync时,查询开始,但不是在当前线程,在新的线程里面,我们查询完数据库后,根据需要做进一步处理,比如,如果原线程UI线程,它将返回以继续处理用户的其他操作(这里非常类似回调方式),否则的话,这个线程就直接被释放了。这段可能比较抽象,会在之后的系列里进一步讲解。
为了更好的进行异步编程,我们需要在方法签名后面追加Async,这是一种异步编程的规约,也希望大家遵守。
虽然异步编程对系统以及用户的体验非常的有帮助,但如果对异步编程不甚了解,可能会发生一些令人感到诡异的问题,而且这些问题可能通过debug方式也很难得到解决。
异步执行流程
1、想象一下,在现实世界中,一个顾客到电脑专卖店买东西,就是那种拿了就走的场景。如果店铺只有一个人,在与顾客1没有结算完成之前,对顾客2的请求,只能暂时放置一下。相信大家在现实世界中,肯定会遇到类似的情况,心情可能也很不爽,如果不是很迫切,可能是再看看,换一家店,如果比较着急,就会一直催,然后也不一定会有回应。
如下图所示
2、有一天,老板请了几个伙计帮忙搬电脑,在顾客1没有结算完成之前,老板就可以接住顾客2的需求,并通过信息系统或者大吼一嗓子的方式,让电脑准备顾客2的电脑。同时,电脑把顾客1的电脑搬到前台,由老板去跟顾客结算,整个的流程就显得体验度很高,顾客也不会被忽略,卖出去的东西也多了很多,不过等待还是要等的。
如下图所示
写在后面
本文主要介绍了异步编程的基础,通过以上介绍,我们知道要创建一个异步函数,首先需要用async去修饰一个方法,同时返回值类型必须是Task或者Task<T>,当然在使用UI控制器时间处理的时候是可以使用async void的。在方法内部,需要使用await关键字。异步函数会被编译器编译成复杂的程序结构,可以视其为一种状态机。不过需要提醒的是,如果不需要编写异步函数,那就用同步。
虽然异步编程已经变得非常简单,但是大家同样需要了解异步编程背后的理念以及原理,这有助于我们编写高性能高扩展的应用程序。
【憩园】C#并发编程之异步编程(一)的更多相关文章
- C#并发编程之异步编程2
C#并发编程之异步编程(二) 写在前面 前面一篇文章介绍了异步编程的基本内容,同时也简要说明了async和await的一些用法.本篇文章将对async和await这两个关键字进行深入探讨,研究其中 ...
- C#复习笔记(5)--C#5:简化的异步编程(异步编程的基础知识)
异步编程的基础知识 C#5推出的async和await关键字使异步编程从表面上来说变得简单了许多,我们只需要了解不多的知识就可以编写出有效的异步代码. 在介绍async和await之前,先介绍一些基础 ...
- .NET “底层”异步编程模式——异步编程模型(Asynchronous Programming Model,APM)
本文内容 异步编程类型 异步编程模型(APM) 参考资料 首先澄清,异步编程模式(Asynchronous Programming Patterns)与异步编程模型(Asynchronous Prog ...
- 【憩园】C#并发编程之异步编程(三)
写在前面 本篇是异步编程系列的第三篇,本来计划第三篇的内容是介绍异步编程中常用的几个方法,但是前两篇写出来后,身边的朋友总是会有其他问题,所以决定再续写一篇,作为异步编程(一)和异步编程(二)的补 ...
- 【憩园】C#并发编程之异步编程(二)
写在前面 前面一篇文章介绍了异步编程的基本内容,同时也简要说明了async和await的一些用法.本篇文章将对async和await这两个关键字进行深入探讨,研究其中的运行机制,实现编码效率与运行效率 ...
- 关于如何提高Web服务端并发效率的异步编程技术
最近我研究技术的一个重点是java的多线程开发,在我早期学习java的时候,很多书上把java的多线程开发标榜为简单易用,这个简单易用是以C语言作为参照的,不过我也没有使用过C语言开发过多线程,我只知 ...
- 如何提高Web服务端并发效率的异步编程技术
作为一名web工程师都希望自己做的web应用能被越来越多的人使用,如果我们所做的web应用随着用户的增多而宕机了,那么越来越多的人就会变得越来越少了,为了让我们的web应用能有更多人使用,我们就得提升 ...
- Java网络编程中异步编程的理解
目录 前言 一.异步,同步,阻塞和非阻塞的理解 二.异步编程从用户层面和框架层面不同角度的理解 用户角度的理解 框架角度的理解 三.为什么使用异步 四.理解这些能在实际中的应用 六.困惑 参考文章 前 ...
- C#复习笔记(5)--C#5:简化的异步编程(异步编程的深入分析)
首先,阐明一下标题的这个“深入分析”起得很惭愧,但是又不知道该起什么名字,这个系列也主要是做一些复习的笔记,供自己以后查阅,如果能够帮助到别人,那自然是再好不过了. 然后,我想说的是异步方法的状态机真 ...
随机推荐
- ReactiveSwift源码解析(六) SignalProtocol的take(first)与collect()延展实现
上篇博客我们聊了observe().map().filter()延展函数的具体实现方式以及使用方式.我们在之前的博客中已经聊过,Signal的主要功能是位于SignalProtocol的协议延展中的, ...
- 【安富莱TCPnet网络教程】HTTP通信实例
第41章 HTTP超文本传输协议基础知识 本章节为大家讲解HTTP(HyperText Transfer Protocol,超文本传输协议),从本章节开始,正式进入嵌入式Web的设计和学习. ...
- 从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】框架之四 || Swagger的使用 3.2
前言 如果想直接在域名的根目录直接加载 swagger 比如访问:localhost:8001 就能访问,可以这样设置: app.UseSwaggerUI(c => { c.SwaggerEnd ...
- .NET Core TDD 前传: 编写易于测试的代码 -- 缝
有时候不是我们不想做单元测试, 而是这代码写的实在是没法测试.... 举个例子, 如果一辆汽车在产出后没完成测试, 那么没人敢去驾驶它. 代码也是一样的, 如果项目未能进行该做的测试, 那么客户就不敢 ...
- 面向对象(__str__和__repr__方法)
#Author : Kelvin #Date : 2019/1/21 16:19 class App: def __init__(self,name): self.name=name # def __ ...
- python接口自动化(二)--什么是接口测试、为什么要做接口测试(详解)
简介 上一篇和大家一起科普扫盲接口后,知道什么是接口,接口类型等,对其有了大致了解之后,我们就回到主题-接口测试. 什么是接口测试 接口测试是测试系统组件间接口的一种测试.接口测试主要用于检测外部系统 ...
- C++11智能指针的深度理解
平时习惯使用cocos2d-x的Ref内存模式,回过头来在控制台项目中觉得c++的智能指针有点生疏,于是便重温一下.首先有请c++智能指针们登场: std::auto_ptr.std::unique_ ...
- 微信公众号开发C#系列-2、微信公众平台接入指南
概述 微信公众平台消息接口的工作原理大概可以这样理解:从用户端到公众号端一个流程是这样的,用户发送消息到微信服务器,微信服务器将接收到的消息post到用户接入时填写的url中,在url处理程序中,首先 ...
- Vb.net MakeLong MAKELPARAM 合并整数代码
Function MAKELPARAM(wLow As UShort, wHigh As UShort) As UInteger Return wHigh * &H10000 + wLow E ...
- 关于TCP的握手与挥手-----简单解释
所谓三次握手(Three-Way Handshake)即建立TCP连接,就是指建立一个TCP连接时,需要客户端和服务端总共发送3个包以确认连接的建立.在socket编程中,这一过程由客户端执行conn ...