C#基础学习 —— 异步编程篇 (二)

基于事件的异步模式是比 IAsyncResult 模式更高级的一种异步编程模式,也被用在更多的场合。对于相对简单的应用程序可以直接用 .Net 2.0 新增的 BackgroundWorker 组件来很方便的实现,对于更复杂的异步应用程序则需要自己实现一个符合基于事件的异步模式的类。这两者对我都是新东西,先从简单的入手,下一篇里我再去尝试复杂类模型的实现

模式概述

支持基于事件的异步模式的类会有若干个 MethodNameAsync 方法表示开始异步操作,并有对应的 MethodNameCompleted 事件。类里面还可能会有 CancelAsync或 MethodNameAsyncCancel 方法用于取消异步操作,并可以有 ProgressChanged 或 MethodNameProgressChanged事件来跟踪执行进度。下面分别作一下解释

MethodNameAsync 方法可以有两个重载:单调用和多调用,多调用有一个额外的状态对象参数 userState。userState 参数用来区分各次异步操作,使得我们可以多次调用多调用形式的方法而不需要等待任何异步操作的完成(在学习 IAsyncResult 模式时我把状态对象仅仅当成传给回调方法的一个条件来用,可能在使用模式时这么做并没有什么关系,但在实现模式时不把状态对象用作异常调用的唯一标识而另作他用就值得商榷了)。而单调用形式的方法如果在前一个调用尚未完成时调用将会抛出 InvalidOperationException 异常

如果有多个异步方法,则应使用 CancelAsync 方法来取消挂起的操作,并可使用 userState 来取消指定的挂起任务。如果只有一个异步方法则可以使用 MethodNameAsyncCancel 方法

另外 MSDN 上说:一次只支持一个挂起的操作的方法(如 Method1Async(string param))是不可取消的。这句话我还没有理解,不可能说是单调用的异步方法就不能取消吧,BackgroundWorker 上都是这样做的

先不管了,接着看ProgressChanged 事件。它有一个 ProgressChangedEventArgs 参数,事件处理程序通过检查该参数的 ProgressPercentage属性来获取任务完成的百分比。如果有多个异步操作挂起,也可以通过检查参数的UserState 属性来分辨操作。如果需要用 ProgressChanged 事件来报告增量结果,则可以把结果保存在派生自 ProgressChangedEventArgs 的类中,并在事件处理程序中使用

BackgroundWorker

BackgroundWorker 很好的符合了事件异步操作模式。它有两个重载版本的 RunWorkerAsync 方法(均为单调用形式)和 RunWorkerCompleted 事件,并有 CancelAsync 方法以及 ProcessChanged 事件。不同的是 BackgroundWorker增加了 DoWork 事件,在 RunWorkerAsync 方法调用时发生,以达到将实际执行的开始方法与 BackgroundWorker 分离的目的。还需要提一下的是 WorkerReportsProcess 属性和ReportProcess 方法,前者指示能否报告进度更新,后者引发 ProcessChanged 事件,它们会在接下来的 Demo 里用到

尝试

因为平时经常要处理几十兆的文本文件,这个 Demo 就做一个读取文件并显示进度的控制台程序。先看类名和字段

class BackgroundWorkerDemo
   {
     private BackgroundWorker m_bw;
     string m_FilePath;
   }

构造函数接收文件路径为参数,设置文件路径并初始化 BackgroundWorker

public BackgroundWorkerDemo(string filePath)
     {
       m_FilePath = filePath;
  m_bw = new BackgroundWorker();
       m_bw.WorkerReportsProgress = true;
       m_bw.DoWork += new DoWorkEventHandler(BackgroundWorker_DoWork);
       m_bw.ProgressChanged += new ProgressChangedEventHandler(BackgroundWorker_ProgressChanged);
       m_bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(BackgroundWorker_RunWorkerCompleted);
     }

时间: 2025-01-20 10:06:31

C#基础学习 —— 异步编程篇 (二)的相关文章

C#基础学习 —— 异步编程篇 (一)

.NET Framework 为异步操作提供了两种设计模式:使用 IAsyncResult 对象的异步操作与使用事件的异步操作.先来学习前者 概述 IAsyncResult 异步设计模式通过名为 BeginOperationName 和 EndOperationName 的两个方法来实现原同步方法的异步调用,如 FileStream 类提供了 BeginRead 和 EndRead 方法来从文件异步读取字节,它们是 Read 方法的异步版本 Begin 方法包含同步方法签名中的任何参数,此外还包

.N“.NET研究”ET中的异步编程(二)- 传统的异步编程

在上一篇文章中,我们从构建响应灵敏的界面以及构建高可伸缩性的服务应用来讨论我们为什么需要异步编程,异步编程能给我们带来哪些好处.那么知道了好处,我们就开始吧,但是在异步编程上海徐汇企业网站制作这个方面,说总是比做简单.套用那句不是名言的名言:编写异步程序是困难的,编写可靠的异步程序尤其困难.因为异步程序非常难以编写,而且非常容易出错,很多基本的构造元素在异步编程中都无法使用,这让我们这些开发人员更愿意编写同步的代码,虽然我们知道有些地方真的应该使用异步. 如何实现异步 对于很多人来说,异步就是使

一起谈.NET技术,.NET中的异步编程(二)- 传统的异步编程

在上一篇文章中,我们从构建响应灵敏的界面以及构建高可伸缩性的服务应用来讨论我们为什么需要异步编程,异步编程能给我们带来哪些好处.那么知道了好处,我们就开始吧,但是在异步编程这个方面,说总是比做简单.套用那句不是名言的名言:编写异步程序是困难的,编写可靠的异步程序尤其困难.因为异步程序非常难以编写,而且非常容易出错,很多基本的构造元素在异步编程中都无法使用,这让我们这些开发人员更愿意编写同步的代码,虽然我们知道有些地方真的应该使用异步. 如何实现异步 对于很多人来说,异步就是使用后台线程运行耗时的

零基础学习SVN之(二):CVS与SVN的区别

相信大家看了零基础学习SVN之(一):SCM与SVN的使用(基础篇)这篇博客之后,对版本控制就有了一定的理解,同时也应该知道SVN与CVS是比较流行的两款SCM工具.那么到底这两款工具有什么区别呢? 1.版本编号方面 例如,我们的版本库为A,其中有文件a,b,c. 在SVN中,新版本的版本号不是针对某个特定文件的,而是针对整个库而言的.提交了5次和提交了6次,文件a有可能不同,也有可能相同,即1.0版和1.1版可能相同.因为第6次提交有可能是因为文件b或c进行了修改.而在CVS中则相反,每次更新

python基础学习笔记(十二)

模块 前面有简单介绍如何使用import从外部模块获取函数并且为自己的程序所用: >>> import math >>> math.sin(0) #sin为正弦函数 0.0   模块是程序 任何python程序都可以作为模块导入.假设写如下程序,并且将它保存为以C:\python\hello.py #hello.py print "hello,world!" 下面通过python解释器调用: >>> import sys >&

为什么用 JavaScript 学习函数式编程?(软件编写)(第二部分)

本文讲的是为什么用 JavaScript 学习函数式编程?(软件编写)(第二部分), 烟雾的方块艺术 -MattysFlicks -(CC BY 2.0) 注意:这是从基础学习函数式编程和使用 JavaScript ES6+ 撰写软件的第二部分.保持关注,接下来还有很多!第一篇 | 第三篇 > 忘掉你认为知道的关于 JavaScript 的一切,用初学者的眼光去看待它.为了帮助你做到这一点,我们将会从头复习一下 JavaScript 的基础,就像你与其尚未谋面一样.如果你是初学者,那你就很幸运了

C#如何使用异步编程

怎么使用异步,就是用委托进行处理,如果委托对象在调用列表中只有一个方法,它就可以异步执行这个方法.委托类有两个方法,叫做BeginInvoke和EndInvoke,它们是用来异步执行使用. 异步有三种模式 等待模式,在发起了异步方法以及做了一些其它处理之后,原始线程就中断,并且等待异步方法完成之后再继续. 轮询模式,原始线程定期检查发起的线程是否完成,如果没有则可以继续做一些其它的事情. 回调模式,原始线程一直在执行,无需等待或检查发起的线程是否完成.在发起的线程中的引用方法完成之后,发起的线程

《鸟哥的Linux 私房菜 基础学习篇(第三版)》——0.3 数据表示方式

0.3 数据表示方式 鸟哥的Linux 私房菜 基础学习篇(第三版) 事实上我们的计算机只认识0与1,记录的数据也是只能记录0与1而已,所以计算机常用的数据是二进制的.但是我们人类常用的数值运算是十进制,文字方面则有非常多的语言,常用的语言就有英文.中文(又分繁体与简体中文).日文等.那么计算机如何记录与显示这些数值/文字呢?就得要通过一系列的转换才可以啦!下面我们就来谈谈数值与文字的编码系统. 0.3.1 数字系统 早期的计算机使用的是利用通电与否的特性的真空管,如果通电就是1,没有通电就是0

async And await异步编程活用基础

原文:async And await异步编程活用基础 好久没写博客了,时隔5个月,奉上一篇精心准备的文章,希望大家能有所收获,对async 和 await 的理解有更深一层的理解. async 和 await 有你不知道的秘密,微软会告诉你吗? 我用我自己的例子,去一步步诠释这个技术,看下去,你绝对会有收获.(渐进描述方式,愿适应所有层次的程序员) 从零开始, 控制台 Hello World: 什么?开玩笑吧?拿异步做Hello World?? 下面这个例子,输出什么?猜猜? 1 static