【憩园】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:简化的异步编程(异步编程的深入分析)
首先,阐明一下标题的这个“深入分析”起得很惭愧,但是又不知道该起什么名字,这个系列也主要是做一些复习的笔记,供自己以后查阅,如果能够帮助到别人,那自然是再好不过了. 然后,我想说的是异步方法的状态机真 ...
随机推荐
- Vue(day4)
这里说的Vue中的路由是指前端路由,与后端路由有所区别.我们可以使用url来获取服务器的资源,而这种url与资源的映射关系就是我们所说的路由.对于单页面程序来说,我们使用url时常常通过hash的方法 ...
- mysql error 2005 - Unknown MySQL server host 'localhost'(11001)
有的时候偶尔会出现这个问题 2005 Unknown MySQL server host 'localhost' (11001),刚开始重启电脑ok了,但是不能每次出现这个问题就重启电脑吧,太麻烦了, ...
- 多元线性回归公式推导及R语言实现
多元线性回归 多元线性回归模型 实际中有很多问题是一个因变量与多个自变量成线性相关,我们可以用一个多元线性回归方程来表示. 为了方便计算,我们将上式写成矩阵形式: Y = XW 假设自变量维度为N W ...
- H5 可堆叠的圆环进度条,支持任意数量子进度条
by Conmajia SN: S22-W1M 由来 看到一篇帖子<vue实用组件--圆环百分比进度条>,让我想起了很多年前我在WinForm下仿制过的Chrome进度条. ▲ 原版进度条 ...
- PHP类和函数注释大全
每次要用PHP的某个功能的时候,都要去查一下,于是决定将PHP所有类和函数都整理出来,加上注释 大致实现 将php.jar文件解压,取出目录stubs 将stubs中的所有php文件中的注释去掉,并做 ...
- winform中使用委托进行窗体之间的传值
一.传统的方式 创建一个公共数据资源类,用于存储窗体2的TextBox的值: public class ComValue { public static string Txtvalue { get; ...
- docker 安装 MySQL 8,并减少内存占用 记录
目前vps 1cpu 512m内存 MySQL内存占用77% ,约350m ,经过修改配置文件优化后如下 $ ps aux 进入docker bash $ docker exec -it pwc-my ...
- InnoSetup 脚本打包及管理员权限设置
InnoSetup使用教程:InnoSetup打包安装 脚本详细 1. 定义变量 #define MyAppName "TranslationTool" #define MyApp ...
- Linux高级运维 第三章 Linux基本命令操作
3.1 Linux终端介绍.Shell提示符.Bash基本语法 3.1.1 登录LINUX终端 两种终端仿真器:1.GNOME桌面的GHOME Terminal : 2.KDE桌面的Konsole ...
- WPF 水印TextBox WatermarkTextBox
//https://blog.csdn.net/puchitomato/article/details/12248691 转自以上链接,自己添加了Enter响应事件. public class ...