一文说通C#中的异步编程补遗

前文写了关于C#中的异步编程。后台有无数人在讨论,很多人把异步和多线程混了。

文章在这儿:一文说通C#中的异步编程

所以,本文从体系的角度,再写一下这个异步编程。

一、C#中的异步编程演变

1. 异步编程模型

这是C#中早期的异步模型,通过IAsyncResult接口来实现。

实现的代码大体是这个样子:

class MyClass
{IAsyncResult BeginAction(para ..., AsyncCallback callback, object state);T EndAction(IAsyncResult async_result);
}

这种方式在一些库里还有保留,像FileSteam类里的BeginReadEndRead方法组,就是这种方式。

编程时,不建议用这种方式。

2. 基于事件的异步模型

这是C#中间一个过渡时期的异步模型,核心是基于一个或多个事件、事件处理委托的派生类型,是一种使用多线程的模式。

这个模式在类库里,多用在Winform/WPF中的组件的事件处理,你可以随便拿一个Framework 4.5以前的组件去研究,大多数都是这种方式。

这种方式的实现大体是这个样子:

class MyClass
{void ActionAsync(para ...);event ActionCompletedEventHandler action_completed;
}

这种方式使用多线程,所以,它具有多线程的全部特点和要求。

从微软的建议来看,Framework 4.5以后,并不推荐使用这种模式。

3. 基于任务的异步模型

这种异步模型从Framework 4.0以后引入,使用单一方法来表示异步的开始和完成。这是目前推荐的异步开发方式。在上个文章中的异步模式,就是这个方式。

这个方式的代码实现是这样的:

class MyClass
{Task<T> ActionAsync(para ...);
}

我们所说的异步,包括前文讲的异步,全部是基于这个基于任务的异步模型来讨论。

在这个模型下,前文说过,异步不是多线程。今天再强调一遍,异步不仅不是多线程,同时异步也不一定会使用多线程。

二、异步模型中的“任务”

先来看看任务:TaskTask<T>,这是异步模型的核心。

这个“任务”,是一种“承诺”,承诺会在稍后完成任务。

它有两个关键字:asyncawait。注意:是await,不是wait。这儿再强调一下,Task.Wait是个同步方法,用在多线程中等待。TaskThread的子集,因此继承了Wait方法,但这个方法不是给异步用的。

在某些情况下,异步可以采用多线程来实现,这时候,Task.Wait可以用,但这是以多线程的身份来使用的,用出问题要查线程,而不是异步。

关于异步中Taskasyncawait配合的部分,可以去看前一个文章。地址在:一文说通C#中的异步编程,这儿不再说了。

三、异步编程的两种模式

1. 单线程模式

先看代码:

Task<string> GetHtmlAsync()
{var client = new HttpClient();var gettask = client.GetStringAsync("https://home.cnblogs.com/u/tiger-wang");return await gettask;
}

这种模式下,这个异步工作于单线程状态。代码虽然返回一个任务Task<T>,在这个任务依然在主线程中,并没有生成一个新的线程。换句话说,这种方式不额外占用线程池资源,也不需要考虑多线程开发中线程锁定、数据一致性等问题

因为线程没有切换,所以也不存在上下文切换的问题

2. 多线程模式

既然Task派生自Thread,当然也可以用多线程来实现异步。

看代码:

Task<string> GetHtmlAsync()
{var gettask = Task.Run(() => {var client = new HttpClient();return client.GetStringAsync("https://home.cnblogs.com/u/tiger-wang");});return await gettask;
}

对方上一段代码,把调用client.GetStringAsync的部分放到了Task.Run里。

这种方式中,异步被放到了主线程以外的新线程中执行,换句话说,这个异步在以多线程的方式执行。

在这种模式下,asyncawait的配合,以及对程序执行次序的控制,跟单线程模式是完全一样的。但是要注意,前边说了,asyncawait是异步的关键字,它不管多线程的事,也不会为多线程提供任何保护。多线程中的并发锁、数据锁、上下文切换,还需要以多线程的方式另外搞定。Task.Run的内部代码会占用线程池资源,并在一个可用的线程上与主线程并行运行。

四、异步的两个额外状态

1. 取消

异步针对的是需要消耗长时间运行的工作。在工作过程中,如果需要,我们可以取消异步的运行。系统提供了一个类CancellationToken来处理这个工作。

定义方式:

Task<T> ActionAsync(para ..., CancellationToken cancellationtoken);

调用方式:

CancellationTokenSource source = new CancellationTokenSource();
CancellationToken cancel_token = source.Token;await ActionAsync(para, cancel_token);

需要取消时:

source.Cancel();

就可以了。

在做API时,异步中加个CancellationToken,是基本的代码礼节。

2. 进度

长时间运行,如果能给出个进度也不错。

定义方式:

Task<T> ActionAsync(para ..., IProgress<T> progress);

其中,T是需要返回的进度值,可以是各种需要的类型。

当然,我们需要实现IProgress:

public class Progress<T> : IProgress<T>  
{  public Progress();  public Progress(Action<T> handler);  protected virtual void OnReport(T value);  public event EventHandler<T> ProgressChanged;  
}  

IProgress<T>通过回调来发送进度值,引发捕获并处理。

全文完。

这篇文章是对前一篇文章的补充和扩展。所以,要两篇一起看,才更好。

一文说通C#中的异步编程

喜欢就来个三连,让更多人因你而受益

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/308424.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java 视频监控 分屏ui_视频监控网页ActiveX视频分屏播放控件开发

最近在搞视频监控项目&#xff0c;需要在网页上显示实时视频&#xff0c;于是网上找了很多资料研究如何在网页上播放视频&#xff0c;一种实现方式就是开发activex控件嵌入到网页中。如下我将介绍如何开发一个可以分屏播放视频的activex控件 (部分内容也是从网上抄的&#xff0…

Java当中 文件得输入流 输出流

一&#xff1a;引言 InputStream 和 OutputStream 两个抽象类&#xff0c;我们主要用其实现类来操作 二&#xff1a;InputStream 输入流&#xff0c;从文件当中读数据到程序当中&#xff0c;我们要站在程序得角度上。 package com.wyj.two;import java.io.File; import jav…

基于.NetCore3.1系列 —— 日志记录之日志核心要素揭秘

前言在上一篇中&#xff0c;我们已经了解了内置系统的默认配置和自定义配置的方式&#xff0c;在学习了配置的基础上&#xff0c;我们进一步的对日志在程序中是如何使用的深入了解学习。所以在这一篇中&#xff0c;主要是对日志记录的核心机制进行学习说明。说明在上一篇中&…

array remove java_how to remove array from another array in javascript

可以将文章内容翻译成中文,广告屏蔽插件会导致该功能失效:问题:0: {id: 1553825061863, name: "Thai Milk Tea", qty: "1", total_amount: 9500, toppings: 500, …}1: {id: 1553825061863, name: "Thai Milk Tea", qty: "1", total_a…

Java 文件的拷贝

一&#xff1a;上码 package com.wyj.two;import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream;/*** 文件…

listview在java中的使用_我的Android开发之路——ListView的使用

在Android开发过程中&#xff0c;遇到需要列表显示的时候&#xff0c;这时候就会用到listview。1.首先创建一个ListViewTest项目&#xff0c;选择empty activity类型。修改activity_main.xml的布局文件&#xff0c;添加listview控件&#xff0c;设置宽高和id等属性此时通过预览…

如何利用NLog输出结构化日志,并在Kibana优雅分析日志?

上文我们演示了使用NLog向ElasticSearch写日志的基本过程(输出的是普通文本日志)&#xff0c;今天我们来看下如何向ES输出结构化日志、在Kibana中分析日志。什么是结构化日志&#xff1f;当前互联网、物联网、大数据突飞猛进&#xff0c;软件越复杂&#xff0c;查找任何给定问题…

C++中字符串的截取 str.substr(a,b);

C中字符串的截取 str.substr(a,b); #include<bits/stdc.h> using namespace std;int main() {//str.substr(a,b);a表示截取字符串的下标&#xff0c;b表示要截取的长度不填则为截取的到最后 string str "aaaabc";cout << str.substr(3) << endl;…

java打印设备集中管理_Kafka+Log4j实现日志集中管理

记录如何使用KafkaLog4j实现集中日志管理的过程。引言前面写的《SpringLog4jActiveMQ实现远程记录日志——实战分析》得到了许多同学的认可&#xff0c;在认可的同时&#xff0c;也有同学提出可以使用Kafka来集中管理日志&#xff0c;于是今天就来学习一下。特别说明&#xff0…

7-27 家谱处理 (30 分)(详解+map做法)map真香啊

一&#xff1a;题目 人类学研究对于家族很感兴趣&#xff0c;于是研究人员搜集了一些家族的家谱进行研究。实验中&#xff0c;使用计算机处理家谱。为了实现这个目的&#xff0c;研究人员将家谱转换为文本文件。下面为家谱文本文件的实例&#xff1a; John Robert Frank Andr…

微软开源基于 Envoy 的服务网格 Open Service Mesh

原文地址&#xff1a;https://techcrunch.com/2020/08/05/microsoft-launches-open-service-mesh/Open Service Mesh&#xff08;OSM&#xff09;是一个轻量级的、可扩展的、云原生的服务网格&#xff0c;它允许用户对高度动态的微服务环境进行统一管理、安全保护&#xff0c;并…

java servlet jsp javabean关系图_Servlet+JSP+JavaBean开发模式(MVC)介绍

好伤心...写登陆注册之前看见一篇很好的博文&#xff0c;没有收藏&#xff0c;然后找不到了。前几天在知乎上看见一个问题&#xff0c;什么时候感觉最无力。前两天一直想回答&#xff1a;尝试过google到的所有solve case&#xff0c;结果bug依然在。今天想回答&#xff1a;明明…

7-28 搜索树判断 (25 分)(思路加详解) just easy!

一&#xff1a;题目 对于二叉搜索树&#xff0c;我们规定任一结点的左子树仅包含严格小于该结点的键值&#xff0c;而其右子树包含大于或等于该结点的键值。如果我们交换每个节点的左子树和右子树&#xff0c;得到的树叫做镜像二叉搜索树。 现在我们给出一个整数键值序列&…

Azure DevOps+Docker+Asp.NET Core 实现CI/CD(一 .简介与创建自己的代理池)

前言本文主要是讲解如何使用Azure DevOpsDocker 来实现持续集成Asp.NET Core项目(当然 也可以是任意项目).打算用三个篇幅来记录完整的全过程觉得有帮助的朋友~可以左上角点个关注,右下角点个推荐CI/CD简介首先,我们先来简单的介绍一下什么是CI/CDCI全拼Continuous Integration…

7-31 笛卡尔树(25分)(题目分析+简单算法+详解+思路)

一&#xff1a;题目 7-31 笛卡尔树 (25 分) 笛卡尔树是一种特殊的二叉树&#xff0c;其结点包含两个关键字K1和K2。首先笛卡尔树是关于K1的二叉搜索树&#xff0c;即结点左子树的所有K1值都比该结点的K1值小&#xff0c;右子树则大。其次所有结点的K2关键字满足优先队列&#…

java ee导入后乱码_JavaEE中为什么出现中文乱码?

1.原因客户端通过IE提交时用的默认编码是UTF-8&#xff0c;而当我们用Myeclipse的时候的服务端接受的时候用的是iso-8859-12.解决方法服务端也用UTF-8编码byte[] result request.getParameter("titile").getBytes("iso-8859-1") ;title new String(resu…

Java多线程之龟兔赛跑和抢票

一&#xff1a;引言 练习这个码主要是为了体验在实现 多线程的方式中 实现Runable接口的好处&#xff0c;其中之一 有共享资源 &#xff0c;一个实现类但可以有多个代理 二&#xff1a;龟兔赛跑 package com.wyj.one; /*** 实现Runable接口也就是可以共享资源* author 86155…

不仅性能秒杀Hadoop,现在连分布式集群功能也开源了

就在昨天&#xff08;2020年8月3日&#xff09;&#xff0c;涛思数据团队正式宣布&#xff0c;物联网大数据平台TDengine集群版开源。此次开源&#xff0c;我们在GitHub上传了23.9万行源代码&#xff0c;1198个源文件&#xff0c;包含我自己疫情期间写的一万余行C代码&#xff…

php 将中文字符转英文字母_php 中英文语言转换类

起初想到制成XML文档形式&#xff0c;这样操作也起来很容易。只是看到说XML效率不怎样再者就是不同的模板&#xff0c;可这样也有个小问题&#xff0c;有些词汇比如时间提示是不确定&#xff0c;与可能是minute &#xff0c;day。也有可能复数加 s那好吧&#xff0c;做成数组&a…

7-32 哥尼斯堡的“七桥问题” (25 分)(思路+详解+题目分析)两种做法任选其一

一&#xff1a;题目&#xff1a; 哥尼斯堡是位于普累格河上的一座城市&#xff0c;它包含两个岛屿及连接它们的七座桥&#xff0c;如下图所示。 可否走过这样的七座桥&#xff0c;而且每桥只走过一次&#xff1f;瑞士数学家欧拉(Leonhard Euler&#xff0c;1707—1783)最终解…