[.net 面向对象程序设计进阶] (19) 异步(Asynchronous) 使用异步创建快速响应和可伸缩性的应用程序
[.net 面向对象程序设计进阶] (19) 异步(Asynchronous) 使用异步创建快速响应和可伸缩性的应用程序
本节导读:
本节主要说明使用异步进行程序设计的优缺点及如何通过异步编程.
使用传统方法BeginInvoke / EndInvoke来实现异步。
使用async/await 创建异步方法和事件。
通过异步编程创建具有快速响应和可伸缩性的应用程序。
读前必备:
1.异步程序设计的优缺点:
A.让用户界面快速响应;对于耗时操作阻塞UI线程,通过异步回调可使用UI快速响应。
B.创建高伸缩性的应用。对于服务端应用,创建更多线程来处理消耗资源较多,使用异步可使用主线程继续工作,不需要等待返回。使用程序具有更好的伸缩性。
对于异步的缺点,最主要一点就是比创建同步程序难度大一些,首先使用传统的方法创建异步,比起同步更容易出错。不过随着.NET的不断发展和第三方异步组件的丰富,创建异步应用程序也变得越来越简单了。
2.异步的实现
对于.NET中的异步编程,.NET在各个方向都几乎提供了同步和异步的两个方式来实现,在这里我们不能把.NET中全部的异步编程方法都列举出来了,下面介绍几种常用且实用的异步方法。
3.使用BeginInvoke / EndInvoke实现异步
3.1 简单的异步示例
下面看一个简单的示例:
//使用一个有返回值的泛型委托来执行BeginInvoke
Func<string> myFunc = new Func<string>(()=>{
Thread.Sleep();
return "我是异步执行完成的返回值 当前时间:" + System.DateTime.Now.ToString();
});
IAsyncResult asynResult = myFunc.BeginInvoke(null, null);
//在异步没有完成前,可以做别的事
while (!asynResult.IsCompleted)
{
//当不是true时,就执行这里的代码
Console.WriteLine("当前异步是否完成:" + asynResult.IsCompleted + " 当前时间:" + System.DateTime.Now.ToString());
}
string result = myFunc.EndInvoke(asynResult);//当是true时,就将结果返回显示 Console.WriteLine(result);
运行结果如下:

在异步没有完成时,可以继续工作做一些想做的事,异步完成后返回结果。
3.2 使用异步的超时 WaitOne 判断异步完成
除了上面使用IsCompleted来判断异步完成之外,也可以使用超时来判断异步的完成情况
示例如下 :
//使用一个有返回值的泛型委托来执行BeginInvoke
Func<string> myFunc = new Func<string>(()=>{
int i = ;
while (i<)
++i;
return "异步执行完成的返回值" + (i).ToString() + " 当前时间:" + System.DateTime.Now.ToString(); });
IAsyncResult asynResult = myFunc.BeginInvoke(null, null); while (!asynResult.AsyncWaitHandle.WaitOne(, false))
Console.Write("*"); string result = myFunc.EndInvoke(asynResult);
Console.Write("\n");
Console.WriteLine(result);
运行结果如下:

3.3 回调
毕竟上述两种等待不是一个好的方法。我们在前端开发中使用过ajax的同学肯定知道,前端中异步使用一个回调函数在异步完成后完成我们想要做的事,.NET自然也有类似的回调方法,
看示例:
//使用一个有返回值的泛型委托来执行BeginInvoke
Func<string> myFunc = new Func<string>(()=>{
int i = ;
while (i<)
++i;
return "异步执行完成的返回值" + (i).ToString() + " 当前时间:" + System.DateTime.Now.ToString(); });
IAsyncResult asynResult = myFunc.BeginInvoke((result) =>
{
string rst = myFunc.EndInvoke(result);
Console.WriteLine("异步完成了,我该返回结果了!");
Console.WriteLine(rst);
}, null);
运行结果如下 :

3.4 其它组件中的Begin\End异步方法
除了BeginInvoke / EndInvoke之外,.NET在很多类中提供了异步的方法,
如System.Net.HttpWebRequest类的BeginGetResponse和EndGetResponse方法,
这里不再一一列举了,使用方法和上面的示例类似。
4. async/await
.NET 5.0 以后,让异步编程变得更加简单了,我们介绍一下async和await。
它让我们编写异步程序变得和同步一样简单,不但减少了代码量,而且不会因为异步让我们程序逻辑被打乱。
4.1 异步方法
下面使用async 和 await关键字来创建一个异步方法,
在第一个方法里调用第二个异步方法,
第二个异步方法中使用了多线程。
听起来很绕口,不过整个代码编写和同步方法没有什么区别,只是多一个关键字。
static void Main(string[] args)
{
Console.WriteLine("主线程开始..");
AsyncMethod();
Thread.Sleep();
Console.WriteLine("主线程结束.."); Console.ReadKey();
} static async void AsyncMethod()
{
Console.WriteLine("开始异步方法");
var result = await MyMethod();
Console.WriteLine("异步方法结束");
} static async Task<int> MyMethod()
{
for (int i = ; i < ; i++)
{
Console.WriteLine("异步执行" + i.ToString() + "..");
await Task.Delay(); //模拟耗时操作
}
return ;
}
运行结果如下:

4.2 异步事件
下面使用一个WinForm应用程序来测试一下异步事件,我们创建一个同步的Click事件和一个异步的Click事件,先触发异步,然后紧接着触发同步,看一下运行结果。
//同步事件
private void button2_Click(object sender, EventArgs e)
{
textBox1.Text += "同步执行开始..\r\n";
MyMethodFirst();
textBox1.Text += "同步执行结束..\r\n";
}
//同事事件调用方法
int MyMethodFirst()
{
for (int i = ; i < ; i++)
{
textBox1.Text += "同步执行" + i.ToString() + "..\r\n";
}
return ;
} //异步事件
private async void button3_Click(object sender, EventArgs e)
{
textBox1.Text += "异步执行开始..====\r\n";
await MyMethodSencond();
textBox1.Text += "异步执行结束..====\r\n";
}
//异步事件调用方法
async Task<int> MyMethodSencond()
{
for (int i = ; i < ; i++)
{
textBox1.Text += "异步执行" + i.ToString() +" ..====\r\n";
await Task.Delay(); //模拟耗时操作
}
return ;
}
运行结果如下:

5. 本节要点
A.使用传统方法BeginInvoke / EndInvoke来实现异步
B.使用async/await 创建异步方法和事件
==============================================================================================
<如果对你有帮助,记得点一下推荐哦,如有有不明白或错误之处,请多交流>
<对本系列文章阅读有困难的朋友,请先看《.net 面向对象编程基础》>
<转载声明:技术需要共享精神,欢迎转载本博客中的文章,但请注明版权及URL>
.NET 技术交流群:467189533 
==============================================================================================
[.net 面向对象程序设计进阶] (19) 异步(Asynchronous) 使用异步创建快速响应和可伸缩性的应用程序的更多相关文章
- [.net 面向对象程序设计进阶] (1) 开篇
[.net 面向对象程序设计进阶] (1) 开篇 上一系列文章<.net 面向对象编程基础>写完后,很多小伙伴们希望我有时间再写一点进阶的文章,于是有了这个系列文章.这一系列的文章中, 对 ...
- [.net 面向对象程序设计进阶] (5) Lamda表达式(一) 创建委托
[.net 面向对象程序设计进阶] (5) Lamda表达式(一) 创建委托 本节导读: 通过学习Lambda表达式,学会创建委托和表达式目录树,深入了解Lambda的特性,让你的代码变的更加清晰. ...
- [.net 面向对象程序设计进阶] (3) 正则表达式 (二) 高级应用
[.net 面向对象程序设计进阶] (2) 正则表达式 (二) 高级应用 上一节我们说到了C#使用正则表达式的几种方法(Replace,Match,Matches,IsMatch,Split等),还 ...
- [.net 面向对象程序设计进阶] (4) 正则表达式 (三) 表达式助手
[.net 面向对象程序设计进阶] (2) 正则表达式(三) 表达式助手 上面两节对正则表达式的使用及.NET下使用正则表达式作了详细说明,本节主要搜集整理了常用的正则表达式提供参考. 此外为了使用方 ...
- [.net 面向对象程序设计进阶] (28) 结束语——告别2015
[.net 面向对象程序设计进阶] (28) 结束语——告别2015 <.net面向对象程序设计进阶>这一系列文章写了太长的时间了,大概有半年没写,在年底又一口气写了好几篇.在整个过程中目 ...
- [.net 面向对象程序设计进阶] (27) 团队开发利器(六)分布式版本控制系统Git——在Visual Studio 2015中使用Git
[.net 面向对象程序设计进阶] (26) 团队开发利器(六)分布式版本控制系统Git——在Visual Studio 2015中使用Git 本篇导读: 接上两篇,继续Git之旅 分布式版本控制系统 ...
- [.net 面向对象程序设计进阶] (26) 团队开发利器(五)分布式版本控制系统Git——图形化Git客户端工具TortoiseGit
[.net 面向对象程序设计进阶] (26) 团队开发利器(五)分布式版本控制系统Git——图形化Git客户端工具TortoiseGit 读前必备: 接上篇: 分布式版本控制系统Git——使用GitS ...
- [.net 面向对象程序设计进阶] (25) 团队开发利器(四)分布式版本控制系统Git——使用GitStack+TortoiseGit 图形界面搭建Git环境
[.net 面向对象程序设计进阶] (25) 团队开发利器(四)分布式版本控制系统Git——使用GitStack+TortoiseGit 图形界面搭建Git环境 本篇导读: 前面介绍了两款代码管理工具 ...
- [.net 面向对象程序设计进阶] (24) 团队开发利器(三)使用SVN多分支并行开发(下)
[.net 面向对象程序设计进阶] (24) 团队开发利器(三)使用SVN多分支并行开发(下) 本篇导读: 接上篇继续介绍SVN的高级功能,即使用分支并行开发.随着需求的不断变更,新功能的增加.特别是 ...
随机推荐
- Java并发集合的实现原理
本文简要介绍Java并发编程方面常用的类和集合,并介绍下其实现原理. AtomicInteger 可以用原子方式更新int值.类 AtomicBoolean.AtomicInteger.AtomicL ...
- Drools 查询学习
Drools 查询学习查询以 query 关键字开始,以 end 关键字结束,在 package 当中一个查询要有唯一的名称,查询的内容就是查询的条件部分,条件部分内容的写法与规则的 LHS 部分写法 ...
- Scrapy shell调试网页的信息
通过scrapy shell "http://www.thinkive.cn:10000/zentaopms/www/index.php?m=user&f=login"
- HTML5的 input:file上传类型控制
一.input:file属性 属性值有以下几个比较常用: accept:表示可以选择的文件MIME类型,多个MIME类型用英文逗号分开,常用的MIME类型见下表. multiple:是否可以选择多个文 ...
- Linux学习笔记(7)-进程
明天开始学习进程,在以前的单片机开发中,都没有进程这个概念,但从网上了解到,这个东西在操作系统中似乎具有很重要的地位,一定好好学习! --------------------------------- ...
- 【统计学习】主成分分析PCA(Princple Component Analysis)从原理到实现
[引言]--PCA降维的作用 面对海量的.多维(可能有成百上千维)的数据,我们应该如何高效去除某些维度间相关的信息,保留对我们"有用"的信息,这是个问题. PCA给出了我们一种解决 ...
- 【原】iOS学习之Masonry第三方约束
1.Masonry概述 目前最流行的Autolayout第三方框架 用优雅的代码方式编写Autolayout 省去了苹果官方恶心的Autolayout代码 大大提高了开发效率 框架地址:https:/ ...
- python文件操作
总是记不住API.昨晚写的时候用到了这些,但是没记住,于是就索性整理一下吧: python中对文件.文件夹(文件操作函数)的操作需要涉及到os模块和shutil模块. 得到当前工作目录,即当前Pyth ...
- 读取hdfs文件之后repartition 避免数据倾斜
场景一: api: textFile("hfds://....").map((key,value)).reduceByKey(...).map(实际的业务计算逻辑) 场景:hdf ...
- Meta标签介绍
Meta标签写法与作用 meta标签是在HTML网页源代码中一个重要的html标签.meta位于head区的辅助性标签,提供用户不可用的信息. META标签用来描述一个HTML网页文档的属性,例 ...