【转】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…

一篇介绍字体的文章

https://www.ituring.com.cn/article/18076

【转】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…

数据结构中“图”的相关概念理解

以下内容为自己的理解&#xff0c;如有错误请指出。 连通 连通和电路中的导通一样。 注意&#xff1a;连通可以是直接连通&#xff0c;也可以经过其他节点后再连通。只要能导通就叫连通。 连通图 任意两个节点间都有路径的图&#xff0c;叫做连通图。 在无向图中&#xff…

【转】使用websocket-sharp来创建c#版本的websocket服务

当前有一个需求&#xff0c;需要网页端调用扫描仪&#xff0c;javascript不具备调用能力&#xff0c;因此需要在机器上提供一个ws服务给前端网页调用扫描仪。而扫描仪有一个c#版本的API&#xff0c;因此需要寻找一个c#的websocket库。 java里有大名鼎鼎的netty&#xff0c;通过…

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

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

OpenGL模板测试通俗理解

看书籍或资料往往还是云里雾里的&#xff0c;这里写一下自己的理解。希望对需要的人有帮助。 简而言之&#xff1a; 模板缓冲区和帧缓冲区一样大模板缓冲区初始状态是什么&#xff1f; 在glClearBuffer的时候清空&#xff0c;所以初始状态是全为0。模板测试什么时候进行&…

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

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

python输出星号_Python的星号(*、**)的作用

1. 函数的可变参数 当函数的参数前面有一个星号*的时候表示这是一个可变的位置参数&#xff0c;两个星号**表示是可变的关键字参数。 #!env python #codingutf-8 # def foo(*args, **kwarg): for item in args: print item for k,v in kwarg.items(): print k,v print 30* if _…

三维GIS开发学习资源

OpenGL OpenGL官网&#xff1a;https://www.opengl.org OpenGL学习网站&#xff1a;https://learnopengl-cn.github.io OSG OSG学习网站&#xff1a;https://osg3.readthedocs.io/en/latest/

【转】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…

常用位运算技巧归纳

位运算在嵌入式编程中比较常用&#xff0c;这里做一下归纳。 应用场景1 假设现有一个32位寄存器AX&#xff0c;定义低位第3位控制一个连着LED的引脚P3&#xff0c;定义位标志数 #define SWITCH_LED 0x0004 FAQ 如何将P3拉高&#xff1f;拉高即置1&#xff0c;使用或运算&a…