【转】1:C#的三种异步的详细介绍及实现

一、介绍异步的前世今生:

  • 异步编程模型 (APM,Asynchronous Programming Model) 模式(也称 IAsyncResult 模式),在此模式中异步操作需要 Begin 和 End 方法(比如用于异步写入操作的 BeginWrite 和 EndWrite)。 对于新的开发工作不再建议采用此模式
  • 基于事件的异步模式 (EAP,Event-based Asynchronous Pattern),这种模式需要 Async 后缀,也需要一个或多个事件、事件处理程序委托类型和 EventArg 派生类型。 EAP 是在 .NET Framework 2.0 中引入的。 对于新的开发工作不再建议采用此模式。
  • 基于任务的异步模式 (TAP, Task-based Asynchronous Pattern) 使用一种方法来表示异步操作的启动和完成。 TAP 是在 .NET Framework 4 中引入的,并且它是在 .NET Framework 中进行异步编程的推荐使用方法。 C# 中的 async 和 await 关键词以及 Visual Basic 语言中的 Async 和 Await 运算符为 TAP 添加了语言支持。

 

二、我这里以一个Read方法为例,将异步操作简单进行讲解:

1.普通操作类

public class MyClass
{public int Read(byte [] buffer, int offset, int count);
}

 

2.异步编程模型(APM)

APM(Asynchronous Programming Model)是.Net 旧版本中广泛使用的异步编程模型。使用了 APM 的异步方法会返回一个 IAsyncResult 对象,这个对象有一个重要的属性 AsyncWaitHandle,他是一个 用来等待异步任务执行结束的一个同步信号。 如果不加 aResult.AsyncWaitHandle.WaitOne() 那么很有可能打印出空白,因为 BeginRead 只是“开始读取”。调用完成一般要调用 EndXXX 来回收资源。  APM 的特点是:方法名字以 BeginXXX 开头,返回类型为 IAsyncResult,调用结束后需要 EndXXX。  .Net 中有如下的常用类支持 APM:Stream、SqlCommand、Socket 等。  APM 还是太复杂,了解即可。 

复制代码

public class MyClass
{public IAsyncResult BeginRead(byte [] buffer, int offset, int count,AsyncCallback callback, object state);public int EndRead(IAsyncResult asyncResult);
}

复制代码

 

3.基于事件的异步模式(EAP)

类似于 Ajax 中的 XmlHttpRequest,send 之后并不是处理完成了,而是在 onreadystatechange 事件中再通知处理完成。

优点是简单,缺点是当实现复杂的业务的时候很麻烦,比如下载 A 成功后再下载 b,如果下载 b 成功再下载 c,否则就下载 d。

EAP 的类的特点是:一个异步方法配一个***Completed 事件。.Net 中基于 EAP 的类比较少。也有更 好的替代品,因此了解即可。

public class MyClass
{public void ReadAsync(byte [] buffer, int offset, int count);public event ReadCompletedEventHandler ReadCompleted;
}

 

4.基于任务的异步模式(TAP)

public class MyClass
{public Task<int> ReadAsync(byte [] buffer, int offset, int count);
}

 

、我这里以一个下载资料方法为例,将异步操作简单进行讲解:

1.普通同步操作

复制代码

private void btn_Click(object sender, EventArgs e)//这是同步按钮{using (WebClient wc = new WebClient()){// 我们尝试去下载 python 的安装包。wc.DownloadFile("https://file.aaoit.com/upload/AllLearnFile/admin//2018/4/24/c558f2dc9d6310bfe3cd1788094d3f0c.pdf", "C#课程第一单元学习.pdf");}label1.ForeColor = Color.Blue;label1.Text = "下载完成。";//提示的label}

复制代码

2.基于事件的异步模式(EAP)

复制代码

private void btnEAP_Click(object sender, EventArgs e)//这是EAP按钮{using (WebClient wc = new WebClient()){// 我们尝试去下载 python 的安装包。// 下载完成时会有事件通知。wc.DownloadFileCompleted += Wc_DownloadFileCompleted;wc.DownloadFileAsync(new Uri("https://file.aaoit.com/upload/AllLearnFile/admin//2018/4/24/c558f2dc9d6310bfe3cd1788094d3f0c.pdf"), "C#课程第一单元学习EAP.pdf");}}private void Wc_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e){label1.ForeColor = Color.Yellow;label1.Text = "下载完成。";//提示的label}

复制代码

 

3.异步编程模型(APM)

复制代码

private void btnAPM_Click(object sender, EventArgs e)//这是APM按钮{FileStream fs = File.OpenRead("e:/cc.txt"); byte[] buffer = new byte[16]; IAsyncResult aResult = fs.BeginRead(buffer, 0, buffer.Length, null, null); aResult.AsyncWaitHandle.WaitOne();//等待任务执行结束 MessageBox.Show(Encoding.UTF8.GetString(buffer));fs.EndRead(aResult); }

复制代码

 

4.基于任务的异步模式(TAP)

复制代码

private async void btnTAP_Click(object sender, EventArgs e)//这是TAP按钮{using (WebClient wc = new WebClient()){// 我们尝试去下载 python 的安装包。Task task = wc.DownloadFileTaskAsync("https://file.aaoit.com/upload/AllLearnFile/admin//2018/4/24/c558f2dc9d6310bfe3cd1788094d3f0c.pdf", "C#课程第一单元学习TAP.pdf");// 可以在这里执行代码。await task;}label1.ForeColor = Color.Red;label1.Text = "下载完成。";//提示的label}

复制代码

 

 

四、TPL(Task Parallel Library)是.Net 4.0 之后带来的新特性,更简洁,更方便。现在在.Net 平台下已经大面积使用。

TPL即任务并行库,是.NET Framework 4版本中的新鲜物,是System.Threading 和 System.Threading.Tasks 命名空间中的一组公共类型和 API。TPL 的目的在于简化向应用程序中添加并行性和并发性的过程,从而提高开发人员的工作效率。 TPL 会动态地按比例调节并发程度,以便最有效地使用所有可用的处理器。此外,TPL 还处理工作分区、ThreadPool 上的线程调度、取消支持、状态管理以及其他低级别的细节操作。通过使用 TPL,您可以在将精力集中于程序要完成的工作,同时最大程度地提高代码的性能。

1.实现读取txt

复制代码

private async void btnTPL_Click(object sender, EventArgs e)//这是TPL按钮{FileStream fs = File.OpenRead("e:/cc.txt");byte[] buffer = new byte[16];int len = await fs.ReadAsync(buffer, 0, buffer.Length);MessageBox.Show("读取了" + len + "个字节");MessageBox.Show(Encoding.UTF8.GetString(buffer)); }

复制代码

注意方法中如果有 await,则方法必须标记为 async,不是所有方法都可以被轻松的标记 为 async。WinForm 中的事件处理方法都可以标记为 async、MVC 中的 Action 方法也可以标 记为 async、控制台的 Main 方法不能标记为 async。  TPL 的特点是:方法都以 XXXAsync 结尾,返回值类型是泛型的 Task<T>。  TPL 让我们可以用线性的方式去编写异步程序,不再需要像 EAP 中那样搞一堆回调、逻 辑跳来跳去了。await 现在已经被 JavaScript 借鉴走了!  用 await 实现“先下载 A,如果下载的内容长度大于 100 则下载 B,否则下载 C”就很容易了 。

2. WebClient 的 TPL 用法: 

 

复制代码

private async void btnTPLWebClientNo_Click(object sender, EventArgs e)//这是TPLUI不卡死按钮{WebClient wc = new WebClient();string html = await wc.DownloadStringTaskAsync("https://www.aaoit.com");//不要丢了 await MessageBox.Show(html); }private void btnTPLWebClientYES_Click(object sender, EventArgs e)//这是TPLUI卡死按钮{WebClient wc = new WebClient();var task = wc.DownloadStringTaskAsync("https://www.aaoit.com"); task.Wait(); MessageBox.Show(task.Result); }

复制代码

WebClient、Stream、Socket 等这些“历史悠久”的类都同时提供了 APM、TPL 风格的 API,甚至有的还提供了 EAP 风格的 API。尽可能使用 TPL 风格的。 

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

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

相关文章

elasticsearch date_Elasticsearch在日志分析领域应用和运维实践

主要讲述了&#xff1a;基于ELK Kafka 的日志分析系统Elasticsearch 优化经验Elasticsearch 运维实践ElasticSearch介绍分布式实时分析搜索引擎&#xff0c;优点包括&#xff1a;查询近实时内存消耗小&#xff0c;搜索速度快可扩展性强高可用数据结构FST(Finite State Transdu…

【转】2:C#TPL探秘

理论&#xff1a; 1、 只要方法是 Task类型的返回值&#xff0c;都可以用 await 来等待调用获取返回值。 2、 如果一个返回 Task类型的方法被标记了 async&#xff0c;那么只要方法内部直接 return T 这个 类型的实例就可以。 3、 一个返回 Task类型的方法没有被标记了 asyn…

Qt添加翻译文件无效或部分无效

原因&#xff1a; QTranslator::load路径错误qApp->installTranslator调用时机应该在所有界面起来之前。命名空间宏导致的问题。如果一个类有命名空间宏&#xff0c;则宏不会转换为命名空间&#xff0c;导致ts文件内的上下文不包含命名空间。上下文对不上导致部分窗口翻译失…

linux shell脚本攻略第3版_「技术干货」师傅说不会写shell脚本的网安不是一个好黑客,实战...

shell脚本&#xff1f;在说什么是shell脚本之前&#xff0c;先说说什么是shell。shell是外壳的意思&#xff0c;就是操作系统的外壳。我们可以通过shell命令来操作和控制操作系统&#xff0c;比如Linux中的Shell命令就包括ls、cd、pwd等等。总结来说&#xff0c;Shell是一个命令…

【转】3:C#异步WaitAll的使用

编写界面如图&#xff1a; private async void button1_Click(object sender, EventArgs e){#region 单个执行的异步&#xff0c;效率慢HttpClient wc new HttpClient();string s1 await wc.GetStringAsync(textBox1.Text);label1.Text s1.Length.ToString();string s2 awa…

Qt实现QTextEdit背景透明

QTextEdit为什么要拿出来单独说&#xff0c;因为它继承自QAbstractScrollArea&#xff0c;一般的设置无效。滚动区域ScrollArea内部有一个widget&#xff0c;需要同时设置ScrollArea和viewport两个窗口才能实现透明。代码如下&#xff1a; m_text_editor->setWindowFlags(Q…

python断点调试_「Python调试器」,快速定位各种疑难杂症!!!

在很多的编辑器其实都带着「调试程序」的功能&#xff0c;比如写 c/c 的 codeblocks&#xff0c;写 Python 的 pycharm&#xff0c;这种图形界面的使用和显示都相当友好&#xff0c;简单方便易学&#xff0c;这个不是我这篇文章要讲的重点。今天主要是想给大家介绍一下 「 Pyth…

【转】C# 温故而知新:Stream篇(—)

目录&#xff1a; 什么是Stream? 什么是字节序列&#xff1f; Stream的构造函数 Stream的重要属性及方法 Stream的示例 Stream异步读写 Stream 和其子类的类图 本章总结 什么是Stream? MSDN 中的解释太简洁了: 提供字节序列的一般视图 &#xff08;我可不想这么理解…

python 画树 递归_数据结构 - python如何递归生成树?

问 题 class Tree: def __init__(self, label): self.root label self.child {} def set_child(self, label, relate): self.child[label] relate def get_root(self): return self.root def get_child(self): return self.child 这么一颗树结构&#xff0c;该如何写 def cr…

java integer valueof_一文读懂什么是Java中的自动拆装箱

本文主要介绍Java中的自动拆箱与自动装箱的有关知识。基本数据类型基本类型&#xff0c;或者叫做内置类型&#xff0c;是Java中不同于类(Class)的特殊类型。它们是我们编程中使用最频繁的类型。Java是一种强类型语言&#xff0c;第一次申明变量必须说明数据类型&#xff0c;第一…

【转】面试:一个单例模式,足以把你秒成渣

去面试&#xff08;对&#xff0c;又去面试&#xff09; 问&#xff1a;单例模式了解吧&#xff0c;来&#xff0c;拿纸和笔写一下单例模式。 我心想&#xff0c;这TM不是瞧不起人吗&#xff1f;我编程十年&#xff0c;能不知道单例模式。 答&#xff1a;&#xff08;.net 平…

【转】SQL 语句执行顺序

From&#xff1a;http://www.jellythink.com/archives/924 Oracle-SQL语句执行原理和完整过程详解&#xff1a;https://wenku.baidu.com/view/398bc427964bcf84b8d57b00.html 详解一条 SQL 语句的执行过程&#xff1a;http://www.cnblogs.com/cdf-opensource-007/p/6502556.h…

堆和栈的概念和区别 python_堆和栈的概念和区别

在说堆和栈之前&#xff0c;我们先说一下JVM&#xff08;虚拟机&#xff09;内存的划分&#xff1a; Java程序在运行时都要开辟空间&#xff0c;任何软件在运行时都要在内存中开辟空间&#xff0c;Java虚拟机运行时也是要开辟空间的。JVM运行时在内存中开辟一片内存区域&#x…

【手算】哈夫曼编码—树形倒置快速画法

哈夫曼编码的原理 参考文章&#xff1a;哈夫曼编码详解——图解真能看了秒懂 简单总结其原理&#xff1a; 需求&#xff1a;对重复出现的元素进行二进制编码&#xff0c;最高效的编码方式是哈夫曼编码。 方法&#xff1a;按照元素出现的频率大小构造一棵树&#xff0c;出现次…

【转】Web API项目中使用Area对业务进行分类管理

在之前开发的很多Web API项目中&#xff0c;为了方便以及快速开发&#xff0c;往往把整个Web API的控制器放在基目录的Controllers目录中&#xff0c;但随着业务越来越复杂&#xff0c;这样Controllers目录中的文件就增加很快&#xff0c;难以管理&#xff0c;而且如果有不同业…

centos部署python flask_用Dockerfile部署你的Flask Web应用

背景故事话说去年年底给另外一个组的同事写了一个简单的工单查询系统&#xff0c;用flask写的&#xff0c;当时是部署在我们组的一台测试物理机上&#xff0c;操作系统是Redhat 7。后来我们组的这台测试物理机要做其它用途&#xff0c;领导给两天时间让把应用迁走&#xff0c;问…

centos7安装flink集群_《从0到1学习Flink》—— Flink 写入数据到 Kafka

前言之前文章 《从0到1学习Flink》—— Flink 写入数据到 ElasticSearch 写了如何将 Kafka 中的数据存储到 ElasticSearch 中&#xff0c;里面其实就已经用到了 Flink 自带的 Kafka source connector&#xff08;FlinkKafkaConsumer&#xff09;。存入到 ES 只是其中一种情况&a…

Qt中的私有信号

一、什么是Qt私有信号&#xff1f; 直接引用Qt文档中的描述&#xff1a; 二、私有信号的作用 私有信号只能被响应&#xff0c;不能被用户代码来发射&#xff08;emit&#xff09;。这是一种对某些信号的权限控制&#xff0c;也就是用户代码没有权力“发号施令”&#xff0c;只…

opencv获取图片像素坐标_利用OpenCV从图片中提取矩形并标注坐标(室内平面地图)(一)

​某城市会展中心室内地图背景一名室内设计师的日常工作从设计一张会展地图开始。常常有这样的场景&#xff1a;划分除规范的展位后&#xff0c;进入销售阶段&#xff0c;频繁的需要修改这张地图&#xff0c;如展示拆分、合并、换位置、标记已交易。问题从上图中标记色块的是有…

【转】C#中ToString()格式详解

以下内容均摘自博客园&#xff0c;仅供资料查询。 ToString格式化 在很多对象显示为字符串的时候都会使用到ToString中的格式化&#xff0c;由于以前没怎么注意到这个问题&#xff0c;想总结一下各个基础结构对象的格式化&#xff0c;以便后备之用&#xff01;&#xff01;&am…