首页 > 编程语言 >C#异步编程

C#异步编程

时间:2022-09-20 21:12:31浏览次数:75  
标签:异步 Task C# 编程 线程 async 方法 await

受众

.Net c#开发人员

概念

免责声明:计算机科学很多概念都没有类似数学一样严谨的定义,以下概念为个人理解

程序(Program)

静态模板

进程(Process)

程序的实例,一个程序可以有多个进程

线程(Thread)

一个进程可以有多个线程,CPU调度分配最小单位

协程(Coroutine)

一个线程有多个协程,用户控制

同步(Synchronous)

执行一个任务只有完成后,才会执行下一个任务

异步(Asynchronous)

执行一个任务不管有没有完成,就开始执行下一个任务,如果任务没有结果则任务完成后会通过状态、通知和回调告知完成。目的是为了提高资源利用率,减少线程等待,而不是为了提高性能,有时使用异步反而性能会降低,但因为减少了等待所以单位时间内做的任务更多了,从而导致性能提升了,所以是用CPU资源换时间

  • 状态:每隔一定时间轮询异步方法的状态,简单但是效率低

  • 通知:异步方法完成后发出通知

  • 回调:与通知类似,异步方法完成后会调用指定的回调函数

同步vs异步

区别在于任务之间是否会等待完成才开始执行,同步有明确的调用链顺序。异步可以类比计算机休眠(Sleep)然后再启动,同步可以类比计算机睡眠(Shut Down)

异步和多线程

多线程是实现异步的其中一种方式,但是异步本身不一定会创建线程,而是任务完成以后系统找寻同步上下文,如果存在则使用之前的同步上下文对应的线程继续执行后续语句,否则自动创建线程执行后续语句;单线程通过事件通知也能做到异步:某个线程去读取某个文件Bytes,CPU告诉磁盘去读取该文件,该线程就返回去做其它任务了,等磁盘通过DMA读取完成该文件完成后通过事件通知该线程,该线程会从内存中拿到文件的Bytes

阻塞(Blocking)

线程挂起 等待某个操作执行完成,期间CPU不会分配时间片给该线程,该线程无法执行其它代码

非阻塞(Non Blocking)

就算某个方法没执行完,线程也会返回

阻塞vs非阻塞

调用者是否一直等待结果,期间不执行其它代码

同步异步 vs 阻塞非阻塞

同步异步关注如何得到结果以及得到结果后如何告知调用者完成,阻塞非阻塞关注如何等待结果,是线程等着完成还是先做其它事情等完成的后通知、回调或者轮询状态。同步和异步与阻塞和非阻塞没有任何关系,所以可以存在4种情况:同步阻塞、同步非阻塞、异步阻塞和异步非阻塞。

同步阻塞

某个线程执行一个同步方法,方法返回结果前, 后续代码不会执行,且该线程一直挂起等待结果,期间不会复用执行其它代码

public static string SyncBlocking()
{
    return SyncDownload();// 线程执行同步方法,并等待它完成期间不做其它任何事情
}
public static string SyncDownload()
{
    var webClient = new WebClient();
    return webClient.DownloadString("https://www.baidu.com");
}

同步非阻塞

某个线程执行一个同步方法,方法没有得到结果前不会返回,该线程会回线程池,期间可能被复用执行其它代码

public static async Task<string> SyncNonBlocking()
{
    // 此处会从线程池中选择一个新线程B执行SyncMethod,如果要具体控制使用哪个线程或者如何排队需要使用Task.Factory.StartNew
    var task = Task.Run(() => SyncDownload());
    var result = await task;// 原线程A执行到此然后马上返回,不等待同步方法完成就返回,这样可以去做其它事情
    return result;
}
public static string SyncDownload()
{
    var webClient = new WebClient();
    return webClient.DownloadString("https://www.baidu.com");
}

异步阻塞

某个线程执行一个异步方法,方法立即返回,后续代码会被执行,直至执行到需要返回结果的代码,该线程挂起等待结果,期间不会复用执行其它代码

public static string AsyncBlocking()
{
    var task = AsyncDownload();
    return task.Result; //虽然是异步操作,但是线程呆呆的等它完成然后获取结果,期间不做其它事情
}
public static Task<string> AsyncDownload()
{
    var webClient = new WebClient();
    return webClient.DownloadStringTaskAsync("https://www.baidu.com");
}

异步非阻塞

某个线程执行一个异步方法,方法立即返回,后续代码会被执行,直至执行到需要返回结果的代码,该线程会回线程池,期间可能被复用执行其它代码

public static async Task<string> AsyncNonBlocking()
{
    var result = await AsyncDownload();// 线程执行到此然后马上返回,可以去做其它事情
    return result;//完成后会获取结果并继续执行后面的代码
}
public static Task<string> AsyncDownload()
{
    var webClient = new WebClient();
    return webClient.DownloadStringTaskAsync("https://www.baidu.com");
}

串行

系统顺序执行多个任务,前一个任务完成后才开始执行下一个任务。同一时刻,只可以有一个任务是开始状态或执行状态

例子:1个处理窗口 1个任务队伍 任务处理完成 移除

时间片1 时间片2 时间片3 时间片4 时间片5

标签:异步,Task,C#,编程,线程,async,方法,await
From: https://www.cnblogs.com/KSPT/p/csharp-async.html

相关文章

  • C# 发送邮件
    一、首先,使用VisualStudio2019创建一个名为“SendMail”的WPF项目,并修改窗口名称。1.打开App.xmal文件,如下图:2.修改App.xmal文件中的启动项,如下图:二、在项目中引入Han......
  • Codeforces Round #821 (Div. 2) ABCD1
    A.ConsecutiveSumhttps://codeforces.com/contest/1733/problem/A题目大意:给定一个长度为n的数组a。最多可以执行k次以下操作:选择两个指数i和j,其中imodk=jmodk......
  • CF1720E Misha and Paintings 题解
    神仙2700。首先统计出原数组中不同元素个数记作\(cnt\),如果\(cnt\lek\)说明元素个数不够,由于一次只能加一个颜色因此答案就是\(k-cnt\)。然后接下来要证明一个结论......
  • mac安装jenkins
    安装jenkins官网给出的命令是:Samplecommands:InstallthelatestLTSversion:brewinstalljenkins-ltsInstallaspecificLTSversion:brewinstalljenkins-lt......
  • Real-Time Ray Tracing 2
    高斯滤波:某一个像素i,周围的像素j(包括i自己)会对其滤波做出贡献,根据j离i的距离,得到高斯对应的值给i。其伪代码大致意思是:根据j离i的距离,算出其对i的贡献,然后用j的值乘以这个......
  • 实验2:Open vSwitch虚拟交换机实践
    实验内容(一)基本要求1.ovs-vsctl基础操作实践:创建OVS交换机,以ovs-xxxxxxxxx命名,其中xxxxxxxxx为本人学号。在创建的交换机上增加端口p0和p1,设置p0的端口号为100,p1的端口号......
  • CSP-S模拟7 序列问题 钱仓 自然数 环路
    T1:线性DP,求最长不下降子序列优化(cdp,树状数组)T2:断环为链,结论T3:序列上区间统计答案,线段树维护T4:咕了,矩阵乘法+分治优化,我就打个暴力T1:给你一个长度n的序列A(n<=5e5,ai<=......
  • 【Coel.学习笔记】随机化算法:模拟退火与爬山法
    简介模拟退火(\(\text{SimulateAnneal}\))和爬山法是随机化算法,二者的原理都在于通过随机生成答案并检查,把答案逐步缩小在一个可行的区间,尽可能地靠近正确答案。在考场......
  • Tomcat异常处理机制
    声明源码基于SpringBoot2.3.12中依赖的Tomcat异常例子tomcat中返回错误页面目前主要是以下两种情况。执行servlet发生异常程序中主动调用response.sendError()方......
  • 17.explicit关键字
    c++提供了关键字explicit,禁止通过构造函数进行的隐式转换。声明为explicit的构造函数不能在隐式转换中使用。[explicit注意]●explicit用于修饰构造函数,防止隐式转化。......