.Net 异步编程详解
2018-06-22 07:47:57来源:未知 阅读 ()
最近看了下关于.Net多线程异步编程的一些文章,趁着这段时间有空,来总结一下吧!
实现异步编程的方式有很多,本文主要选择4种方式概述下,谈谈自己的一些理解!
第一种方法:使用异步委托。
我们知道,C#在处理delegate关键字的时候,动态生成了两个方法:BeginInvoke()和EndInvoke()。其中BeginInvoke()方法返回的对象实现了IAsyncResult接口,而EndInvoke()方法需要一个IAsyncResult类型作为参数。所以,由BeginInvoke()方法返回的对象IAsyncResult,它允许调用的线程在后面通过EndInvoke()方法来获取异步方法返回的结果。为更直观的理解,下面直接通过例子来说明吧!
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace test1 { class Program { static void Main(string[] args) { Async(); } /// <summary> /// 定义一个委托 /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <returns></returns> private delegate int DelegaIn(int x, int y); private static void Async() { //输出正在执行的线程ID Console.WriteLine("输出正在执行的线程ID:" + System.Threading.Thread.CurrentThread.ManagedThreadId); //异步模式下调用 DelegaIn delegaObj = new DelegaIn(Add); IAsyncResult async = delegaObj.BeginInvoke(10, 20,null,null); //主线程继续执行其他任务 Console.WriteLine("主线程继续执行其他任务!!!"); int answer = delegaObj.EndInvoke(async); Console.WriteLine("Add方法结束结果:" + answer); } private static int Add(int x, int y) { System.Threading.Thread.Sleep(1000 * 5); //输出次线程ID Console.WriteLine("输出次线程ID:" + System.Threading.Thread.CurrentThread.ManagedThreadId); Console.WriteLine("Add方法开始"); return x + y; } } }
然后来看结果:
我们可以看到控制台先是输出当前线程的ID,然后下一步我们看到会在异步模式下调用Add方法,并且Add方法还使用Sleep挂起了5秒,但我们的程序并没有被阻塞等待,而是直接输出主线程继续执行其他任务,最后等待异步返回结果。而且可以看到Add方法里面其实是创建了由运行时维护的工作者线程,它的线程ID是3。这就是使用异步委托的方式来异步编程,当然,这只是一个简单的异步例子,关于IAsyncResult接口还提供其他的一些操作,这里就不做过多的概述了。
第二种方法:使用System.Threading 下的Thread类。
使用线程类Thread。其实就是手动给当前程序创建一个次线程:
1、创建一个ThreadStart (或者ParameterizedThreadStart) 委托。并把定义的方法地址传给委托。值得注意的是,ThreadStart 委托指向的是无返回值,无参数的方法。而ParameterizedThreadStart委托指向的是有参数的方法。
2、创建一个Thread对象,并把上述委托传递进来
3、调用Thread.Start() 方法
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace test2 { class Program { static void Main(string[] args) { RunThread(); } private static void RunThread() { //输出正在执行的线程ID Console.WriteLine("输出正在执行的线程ID:" + System.Threading.Thread.CurrentThread.ManagedThreadId); ThreadStart threadStart = new ThreadStart(Print); Thread thread = new Thread(threadStart); thread.Start(); //主线程继续执行其他任务 Console.WriteLine("主线程继续执行其他任务!!!"); } private static void Print() { System.Threading.Thread.Sleep(1000 * 5); //输出次线程ID Console.WriteLine("输出次线程ID:" + System.Threading.Thread.CurrentThread.ManagedThreadId); Console.WriteLine("Print方法结束"); } } }
看结果和上面使用异步委托差不多。只不过这是我们使用手动创建次线程的方法来实现异步的。
第三种方法:使用TPL并行编程库。
.Net4.0开始,微软引入了种新的多线程应用程序开发方法,即TPL并行编程库。其中使用Task类不必再直接的与线程和线程池打交道。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Threading; namespace test3 { class Program { static void Main(string[] args) { //输出正在执行的线程ID Console.WriteLine("输出正在执行的线程ID:" + System.Threading.Thread.CurrentThread.ManagedThreadId); Task.Factory.StartNew(Print); //主线程继续执行其他任务 Console.WriteLine("主线程继续执行其他任务!!!"); Console.ReadLine(); } private static void Print() { System.Threading.Thread.Sleep(1000); //输出次线程ID Console.WriteLine("输出次线程ID:" + System.Threading.Thread.CurrentThread.ManagedThreadId); Console.WriteLine("Print方法结束"); } } }
结果:
Task类可以轻松在次线程中调用方法,可以作为异步委托的简单替代品!!!
第四种方法:async和await异步调用。
最后,来介绍下.Net4.5下新增的两个关键字。async和await。
async关键字用来指定某个方法、Lambda表达式自动以异步的方式调用。通过async修改的方法,CLR会创建新的执行线程来处理任务。在调用async方法时,await会自动挂起当前线程,直到任务完成,离开async修饰的调用线程,才继续往下执行。
我们来看一个Windows Forms 程序。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace ParallerForm { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { ProcessFiles(); btnImage1.Text = "主线程执行完毕"; } private void ProcessFiles() { Thread.Sleep(3000); btnImage.Text = "次线程执行完毕"; } } }
当点击按钮的时候,需要等待3秒钟,文本框才能接收到键盘的输入,整个窗体这个时候就是个阻塞状态。现在来使用async关键字修饰方法,使其异步执行。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace ParallerForm { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private async void button1_Click(object sender, EventArgs e) { await ProcessFiles(); btnImage1.Text = "主线程执行完毕"; } private async Task ProcessFiles() { await Task.Run(() => { Thread.Sleep(3000); btnImage.Text = "次线程执行完毕"; }); } } }
你会发现,点击按钮后,窗体不会阻塞,可以立即在文本区输入值。因为async关键字允许它以非阻塞的形式进行工作。然后在遇到await关键字的时候,线程将挂起,指导await的任务完成。同时,控制权将返回给方法的调用者。
好了!到此为止,上文总共介绍了4种异步编程的方式,文中如有什么不妥之处,还望大家不吝赐教!!!
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- asp.net源程序编译为dll文件并调用的实现过程 2020-03-29
- Asp.net MVC SignalR来做实时Web聊天实例代码 2020-03-29
- ASP.NET MVC中jQuery与angularjs混合应用传参并绑定数据 2020-03-29
- Asp.Net中WebForm的生命周期 2020-03-29
- ASP.NET使用Ajax返回Json对象的方法 2020-03-23
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash