[.net 面向对象程序设计进阶] (19) 异步(Asynchronous) 使用异步创建快速响应和可伸缩性的应用程序

本节导读:

本节主要说明使用异步进行程序设计的优缺点及如何通过异步编程.

使用传统方法BeginInvoke / EndInvoke来实现异步。

使用async/await 创建异步方法和事件。

通过异步编程创建具有快速响应和可伸缩性的应用程序。

读前必备:

A.委托 [.net 面向对象编程基础]  (21) 委托

B.事件 [.net 面向对象编程基础] (22)事件

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) 使用异步创建快速响应和可伸缩性的应用程序的更多相关文章

  1. [.net 面向对象程序设计进阶] (1) 开篇

    [.net 面向对象程序设计进阶] (1) 开篇 上一系列文章<.net 面向对象编程基础>写完后,很多小伙伴们希望我有时间再写一点进阶的文章,于是有了这个系列文章.这一系列的文章中, 对 ...

  2. [.net 面向对象程序设计进阶] (5) Lamda表达式(一) 创建委托

    [.net 面向对象程序设计进阶] (5) Lamda表达式(一)  创建委托 本节导读: 通过学习Lambda表达式,学会创建委托和表达式目录树,深入了解Lambda的特性,让你的代码变的更加清晰. ...

  3. [.net 面向对象程序设计进阶] (3) 正则表达式 (二) 高级应用

    [.net 面向对象程序设计进阶] (2) 正则表达式 (二)  高级应用 上一节我们说到了C#使用正则表达式的几种方法(Replace,Match,Matches,IsMatch,Split等),还 ...

  4. [.net 面向对象程序设计进阶] (4) 正则表达式 (三) 表达式助手

    [.net 面向对象程序设计进阶] (2) 正则表达式(三) 表达式助手 上面两节对正则表达式的使用及.NET下使用正则表达式作了详细说明,本节主要搜集整理了常用的正则表达式提供参考. 此外为了使用方 ...

  5. [.net 面向对象程序设计进阶] (28) 结束语——告别2015

    [.net 面向对象程序设计进阶] (28) 结束语——告别2015 <.net面向对象程序设计进阶>这一系列文章写了太长的时间了,大概有半年没写,在年底又一口气写了好几篇.在整个过程中目 ...

  6. [.net 面向对象程序设计进阶] (27) 团队开发利器(六)分布式版本控制系统Git——在Visual Studio 2015中使用Git

    [.net 面向对象程序设计进阶] (26) 团队开发利器(六)分布式版本控制系统Git——在Visual Studio 2015中使用Git 本篇导读: 接上两篇,继续Git之旅 分布式版本控制系统 ...

  7. [.net 面向对象程序设计进阶] (26) 团队开发利器(五)分布式版本控制系统Git——图形化Git客户端工具TortoiseGit

    [.net 面向对象程序设计进阶] (26) 团队开发利器(五)分布式版本控制系统Git——图形化Git客户端工具TortoiseGit 读前必备: 接上篇: 分布式版本控制系统Git——使用GitS ...

  8. [.net 面向对象程序设计进阶] (25) 团队开发利器(四)分布式版本控制系统Git——使用GitStack+TortoiseGit 图形界面搭建Git环境

    [.net 面向对象程序设计进阶] (25) 团队开发利器(四)分布式版本控制系统Git——使用GitStack+TortoiseGit 图形界面搭建Git环境 本篇导读: 前面介绍了两款代码管理工具 ...

  9. [.net 面向对象程序设计进阶] (24) 团队开发利器(三)使用SVN多分支并行开发(下)

    [.net 面向对象程序设计进阶] (24) 团队开发利器(三)使用SVN多分支并行开发(下) 本篇导读: 接上篇继续介绍SVN的高级功能,即使用分支并行开发.随着需求的不断变更,新功能的增加.特别是 ...

随机推荐

  1. Windows Task Scheduler Fails With Error Code 2147943785

    Problem: Windows Task Scheduler Fails With Error Code 2147943785 Solution: This is usually due to a ...

  2. ORA-12638:身份证明检索失败

    本地Sqlplus 连一远程数据库,出现 ORA-12638: 身份证明检索失败,pl/sql developer 也是同样的问题,tnsping 是没有问题的. 找到本地的sqlnet.ora文件, ...

  3. cocos2d-x 从win32到android移植的全套解决方案

    引言:我们使用cocos2d-x引擎制作了一款飞行射击游戏,其中创新性地融入了手势识别功能.但是我们在移植过程中遇到了很多的问题,同时也发现网上的资料少而不全.所以在项目行将结束的时候,我们特地写了这 ...

  4. WM_COPYDATA实现的不同进程间通信

    进程间通信,通过SendMessage向另一进程发送WM_COPYDATA消息,实现不同进程间的消息通信. 需求:已写好一个工具软件,想在不更改当前的软件开发的前提下,实现为后面新开发的软件提供数据推 ...

  5. 在IIS8.5的环境下配置WCF的Restful Service

    今天在客户的环境中(Windows Server 2012 R2 + IIS 8.5)搭建Call WCF Restful Service的功能,发现了几个环境配置的问题,记录如下: 1):此环境先安 ...

  6. java内存泄露

    上一篇提到的是java垃圾回收,今天谈谈java的内存泄露. 首先谈下java的内存管理机制: 在Java程序中,我们通常使用new为对象分配内存,而这些内存空间都在堆(Heap)上. public ...

  7. Node.js之创建应用

    1.使用Node.js时,不仅仅在实现一个应用,同时实现了整个HTTP服务器: 2.Node.js由下列几部分组成: (1)引入required模块:我们可以使用require指令来载入Node.js ...

  8. LINUX 查看当前系统的内存使用情况

    # free 显示结果如下: Mem:表示物理内存统计 total 内存总数 8057964KB used 已使用的内存 7852484KB free 空闲的内存数 205480KB shared 当 ...

  9. Node使用multiparty包上传文件

    var multiparty = require('multiparty'); var http = require('http'); var util = require('util'); var ...

  10. 并查集+树链剖分+线段树 HDOJ 5458 Stability(稳定性)

    题目链接 题意: 有n个点m条边的无向图,有环还有重边,a到b的稳定性的定义是有多少条边,单独删去会使a和b不连通.有两种操作: 1. 删去a到b的一条边 2. 询问a到b的稳定性 思路: 首先删边考 ...