[.net 面向对象程序设计进阶] (19) 异步(Asynchronous) 使用异步建立快速响应和可伸缩性的应用程序
html
本节导读:前端
本节主要说明使用异步进行程序设计的优缺点及如何经过异步编程.ajax
使用传统方法BeginInvoke / EndInvoke来实现异步。编程
使用async/await 建立异步方法和事件。多线程
经过异步编程建立具备快速响应和可伸缩性的应用程序。 异步
读前必备:async
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(10); 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 = 0; while (i<99999999) ++i; return "异步执行完成的返回值" + (i).ToString() + " 当前时间:" + System.DateTime.Now.ToString(); }); IAsyncResult asynResult = myFunc.BeginInvoke(null, null); while (!asynResult.AsyncWaitHandle.WaitOne(10, 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 = 0; while (i<99999999) ++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(1000); Console.WriteLine("主线程结束.."); Console.ReadKey(); } static async void AsyncMethod() { Console.WriteLine("开始异步方法"); var result = await MyMethod(); Console.WriteLine("异步方法结束"); } static async Task<int> MyMethod() { for (int i = 0; i < 5; i++) { Console.WriteLine("异步执行" + i.ToString() + ".."); await Task.Delay(1000); //模拟耗时操做 } return 0; }
运行结果以下:
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 = 0; i < 5; i++) { textBox1.Text += "同步执行" + i.ToString() + "..\r\n"; } return 0; } //异步事件 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 = 0; i < 5; i++) { textBox1.Text += "异步执行" + i.ToString() +" ..====\r\n"; await Task.Delay(1000); //模拟耗时操做 } return 0; }
运行结果以下:
5. 本节要点
A.使用传统方法BeginInvoke / EndInvoke来实现异步
B.使用async/await 建立异步方法和事件
==============================================================================================
<若是对你有帮助,记得点一下推荐哦,若有有不明白或错误之处,请多交流>
<对本系列文章阅读有困难的朋友,请先看《.net 面向对象编程基础》>
<转载声明:技术须要共享精神,欢迎转载本博客中的文章,但请注明版权及URL>
==============================================================================================