异步编程模式学习

      最近,在学习C#多线程编程,也看了园子里的很多大牛的关于多线程的文章,梳理下自己的思路,也总结下异步编程模式的学习。

     很喜欢Jimmy Zhang的文章风格,在刚刚学习委托和事件的时候,Jimmy的文章的由浅入深的写作对我对委托和事件的学习的帮助很大。我也学这个Jimmy的文风,和大家交流下。废话不多说的,通过一个抛12点的小游戏的例子进入正题。

    没有异步模式的多线程实现                        

       游戏的规则:游戏随机产生的0到12之间的数字,碰到数字12游戏结束。实现如下:例1

static void Main(string[] args){Thread thread = new Thread(new ThreadStart(ThreadFun));thread.Start();Console.WriteLine("Game is starting...");thread.Join();Console.WriteLine("Number 12 is createed.Game is over...");Console.ReadKey();}static void ThreadFun(){Random rnd = new Random();int rndNum;do{rndNum = rnd.Next(0, 13);Console.WriteLine(rndNum);} while (rndNum != 12);}

 

       异步编程模式的实现

 这个小游戏的异步模式编程实现如下代码:例2

delegate void asycInvoker();static void Main(string[] args){asycInvoker asycHander = ThreadFun;//此处是asycInvoker asycHander = new asycInvoker(ThreadFun)的快捷语法IAsyncResult result = asycHander.BeginInvoke(null,null);Console.WriteLine("Game is starting...");asycHander.EndInvoke(result);Console.WriteLine("Number 12 is createed.Game is over...");Console.ReadKey();}static void ThreadFun(){Random rnd = new Random();int rndNum;do{rndNum = rnd.Next(0, 13);Console.WriteLine(rndNum);} while (rndNum != 12);}

    异步编程模式和多线程的关系

     异步编程模式技术为多线程处理技术的强大扩展方式。C#的异步模式的内部的实现是通过线程池的挂起和释放实现一步操作。C#的异步模式的好处降低创建和销毁线程相关的成本,CLR为每一个进程维护一个线程池。

     由此,我们必须清楚线程池的优缺点的。线程池的优点是很明显的,缺点是一旦加入线程池,就没办法控制程序的执行,程序的执行都在线程池的自动管理。

   .NET的异步编程模式

      Net 在设计的时候为异步编程设计了一个异步编程模型(APM),这个模型不仅是使用.NET的开发人员使用,.Net内部也频繁用到。通过使用委托,我们可以异步实现委托列表上的方法(委托列表只能有一个方法)。委托类有两个方法:叫做BeginInvoke和EndInvoke,他们就是用来实现异步操作过程。

      当我们调用委托的BeginInvoke方法时,它开始在线程池中的独立线程上执行引用方法,并且立即返回原始线程。原始线程可以继续,而引用方法会在线程池的线程中执行。

     当程序异步方法执行的时候,主线程和异步方法的线程池线程之间的同步过程不同处理,就会有不同的实现模式,当异步方法执行结束,可以检查BeginInvoke返回的IAsyncResult的IsCompleted属性,或者调用委托的EndInvoke方法等待委托的完成,或着在委托的回调方法中调用EndInvoke方法完成委托。

     上述过程有异步编程的3种标准模式的过程。这三种过程,原始线程都发起了一个异步方法,这些模式不同的是,原始线程获得发起的线程已经完成的消息的方式。标准的三种模式有等待完成模式、轮询模式和回调模式。通过代码将每一种模式表述下:

      等待-结束模式

     在这个模式中,原始线程发起异步模式方法的调用,原始线程和异步方法所在的线程池线程并发(可能这里用并发描述不是很恰当)运行,如果原始线程一直到调用委托方法的EndInvoke时,委托方法还没有执行完,原始线程就等待异步线程结束,如果有返回值的话,返回异步方法的返回值。代码如例1所示。

     AsyncResult类

       在BeginInvoke方法的调用的时候,返回一个IAsyncResult接口的引用,在内部实现AsyncResult类的对象。AsyncResult类表现了异步方法的状态。有关这个类的需要说明的如下:

  •  我们调用委托对象的BeginInvoke方法时,系统创建了一个AsyncResult类的对象。BeingInvoke方法返回对象实现的接口的引用。
  • AsyncResult对象包含一个叫做AsyncDelegate的属性,该属性返回指向被调用的产生异步方法的委托对象的引用。
  • IsCompleted属性表示异步方法是否完成。
  • AsyncState属性作为BeginInvoke方法调用时的state参数,他返回object类型的引用。

 

    轮询模式

       在轮询模式中,原始线程发起的异步方法的调用,原始线程就继续执行,然后用IasyncResult的IsComplete属性来定期检查异步线程是否完成。如果异步方法已经完成,原始线程就调用EndInvoke并继续,否则,继续检查执行。代码实例3

 delegate void asycInvoker();static void Main(string[] args){asycInvoker asycHander = new asycInvoker(ThreadFun);IAsyncResult result = asycHander.BeginInvoke(null,null);Console.WriteLine("Game is starting...");while (!result.IsCompleted){Console.WriteLine("Game is not completed...");//此处可以继续执行其他的逻辑
            }asycHander.EndInvoke(result);Console.WriteLine("Number 12 is createed.Game is over...");Console.ReadKey();}static void ThreadFun(){Thread.Sleep(100);//暂时挂起该线程,放大整个执行的过程Random rnd = new Random();int rndNum;do{rndNum = rnd.Next(0, 13);Console.WriteLine(rndNum);} while (rndNum != 12);}

     回调模式

     在前面的模式中,等待-结束和轮询模式中,初始线程都是继续自己的执行过程,等待异步的线程完成。然后,在EndInvoke获得异步方法的返回值,并初始线程继续后面的逻辑执行。在效率地上,轮询通常不是最好的方法。所以,在异步编程中使用通知机制,能在一个异步方法完成时触发一个方法。

      我们回到BeginInvoke方法的参数来谈的,BeginInvoke的参数根据定义的委托类型不断变化的,但是最后两个参数是不会改变的,AsyncCllback委托类型的原型为:delegate void AsyncCallback(IAsyncResult result),最后一个参数为object类型,稍后会谈到object类型解决的问题。回调的方法的通知机制关键就在AsyncCllback委托类型参数的使用,在AsyncCallback委托的实例中调用EndInvoke方法,返回异步方法的返回值,而AsyncCallback实例在异步方法一结束就调用。通过代码演练实例4:

 delegate void asycInvoker();static void Main(string[] args){asycInvoker asycHander = new asycInvoker(ThreadFun);IAsyncResult result = asycHander.BeginInvoke(new AsyncCallback(CallbackFun),null);Console.WriteLine("Game is starting...");Console.ReadKey();}static void CallbackFun(IAsyncResult result){AsyncResult asyncResult = (AsyncResult)result;asycInvoker handler = (asycInvoker)asyncResult.AsyncDelegate;handler.EndInvoke(result);Console.WriteLine("Number 12 is createed.Game is over...");}static void ThreadFun(){Console.WriteLine("asyncMethod is runing...");Random rnd = new Random();int rndNum;do{rndNum = rnd.Next(0, 13);Console.WriteLine(rndNum);} while (rndNum != 12);}

回调过程传递参数

       为能具体的展示object类型参数的应用,这次将这个小程序的要求改变一下,我们可以随机选择结束的数字,游戏在产生我们需要的数字时结束。通过代码的演示例5

 delegate void asycInvoker(int endNum);static void Main(string[] args){Console.WriteLine("Select the End Number:");int endNum = int.Parse(Console.ReadLine());asycInvoker asycHander = new asycInvoker(ThreadFun);IAsyncResult result = asycHander.BeginInvoke(endNum,new AsyncCallback(CallbackFun),endNum);Console.WriteLine("Game is starting...");Console.ReadKey();}static void CallbackFun(IAsyncResult result){int endNum = (int)result.AsyncState;AsyncResult asyncResult = (AsyncResult)result;asycInvoker handler = (asycInvoker)asyncResult.AsyncDelegate;handler.EndInvoke(result);Console.WriteLine("Number {0} is createed.Game is over...",endNum);//此处为传递的参数的用途
        }static void ThreadFun(int endNum){Console.WriteLine("asyncMethod is runing...");Random rnd = new Random();int rndNum;do{rndNum = rnd.Next(0, endNum);Console.WriteLine(rndNum);} while (rndNum != 12);}

     关于异步编程的使用,推荐老赵的博客写到的正确使用异步操作。

        以上是我对学习异步编程模式的知识的梳理,在大神云集的园子里,作为.NET入门新手,不求闻达,希望能为园子里乐于分享的精神能有所发扬,也希望能对园子里的新手们有所帮助,能得到牛人的指导。

 

 

       

 

 

 

 

 

    

    

 

转载于:https://www.cnblogs.com/Johnnie/archive/2012/08/20/Async.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/296723.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

坚持不懈,直到成功

坚持不懈,直到成功。 在古老的东方,挑选小公牛到技场格斗有一定的程序。它们被带进场,向手持长的斗士攻击,裁判以它受戳后再向斗牛士进攻的次数多来评定这只公牛的勇程度。从今往后,我须承认,我的生命每天都…

增长率不用计算机,事业单位行测:这类资料分析题根本不用计算

【导读】中公事业单位为帮助各位考生顺利通过事业单位招聘考试,今天为大家带来事业单位行政职业能力测试备考资料。很多同学认为资料分析列式容易,计算很难。但是,你知道吗?资料分析中有这几类题目是完全不需要动笔计算的,只要列…

在Web应用中使用localforage存储离线数据

在现代Web应用中,我们经常会需要在本地存储一些数据,一方面记住用户的一些状态,或个性化设置,尤其是可以缓存一些常用(甚至全部)的数据,实现更加强大和丰富的本地交互体验。传统上说&#xff0c…

CodeForces 486C Palindrome Transformation 贪心+抽象问题本质

题目:戳我 题意:给定长度为n的字符串,给定初始光标位置p,支持4种操作,left,right移动光标指向,up,down,改变当前光标指向的字符,输出最少的操作使得字符串为回…

出差一定要给孩子带特产

1 这就是热恋期管不住自己的情侣▼2 热恋期过了...▼3 这该夸你腰细呢?还是脸大呢?▼4 听起来...不是挺好的吗▼5 由于新冠病毒,美国GCW选手都保持着一定距离改用原力来进行比赛▼6 她们太菜了你跟她们好以后肯定疯狂掉分▼7 出差一定…

comment desc显示表结构_MySQL 查看表结构简单命令

一、简单描述表结构,字段类型desc tabl_name;显示表结构,字段类型,主键,是否为空等属性,但不显示外键。例如:desc table_name二、查询表中列的注释信息select * from information_schema.columnswhere tabl…

Android培训翻译_允许其他应用程序启动你的Activity

This lesson teaches you to Add an Intent Filter 添加一个意图过滤器 Handle the Intent in Your Activity 在你的Activity中处理Intent Return a Result 返回结果 You should also read Sharing Content 共享内容 The previous two lessons focused on one side of the stor…

话里话外:浅谈国企绩效考核问题(二)

企业在进行绩效考核的过程中,很容易忽略一些问题: 一、对绩效考核认识不足;绩效考核是企业管理的重头戏,它可以使企业的活动更加高效,提升员工的积极性。但与此同时,绩效考核也是一把双刃剑,绩效…

计算机用户名密码策略,设置域用户帐户密码策略

从安全和易用考虑,普通域用户的帐户策略必须满足一下要求:u 密码长度至少3位u 最长使用期限60天u 密码必须符合复杂性要求u 密码最短使用0天u 帐户锁定阀值7次u 帐户锁定时间30分钟u 复位帐户锁定计数器30分钟任务:u 使用默认域策略设置域用户帐户策略u …

NGINX轻松管理10万长连接

一 前言当管理大量连接时,特别是只有少量活跃连接,NGINX有比较好的CPU和RAM利用率,如今是多终端保持在线的时代,更能让NGINX发挥这个优点。本文做一个简单测试,NGINX在一个普通PC虚拟机上维护100k的HTTP长连接&#xf…

从 MVC 到使用 ASP.NET Core 6.0 的Minimal API

从 MVC 到使用 ASP.NET Core 6.0 的Minimal APIhttps://benfoster.io/blog/mvc-to-minimal-apis-aspnet-6/2007 年,随着 ASP.NET MVC 引入了其他语言中变得司空见惯的模型-视图-控制器模式[1],并为其提供原生支持,.NET Web 应用程序开发有了极…

优秀的硕博士们,他们的朋友圈都有什么特点?

全世界只有3.14 % 的人关注了爆炸吧知识很多同学都会有这种感觉,读了硕士博士后,兴趣会突然间发生很大变化,发朋友圈也会不一样了。例如,合格的学术研究者,要快速、全面的获取各种最新文献和学界动态;还要持…

Android学习笔记(1)

Activity就是展示的界面 创建Activity的要点: 1、一个Activity就是一个类,并且要继承Activity 2、需要复写onCreate方法 3、每一个Activity都需要注册在AndroidManifest.xml文件中注册 4、为Activity添加必要控件 Intent作用是传输数据转载于:https://ww…

linux__ftp

构建基于虚拟用户的vsftpd服务器并使数据加密传输一、首先配置你的yum源,确保路径正确。vim /etc/yum.repos.d/server.repo(如果你的已经配置了,可以忽略此项)关闭你的selinux避免出现不必要的错误Setenforce 0二、安装vsftpdyum install vsftpdservice …

未来教育计算机二级Excel解析,Excel操作小技巧,助你学好计算机二级office!

原标题:Excel操作小技巧,助你学好计算机二级office!Office考试中最难的是什么?当然是Excel函数啊!小编辛苦整理了excel10大懒人技巧,让你考试速提分!还不赶紧收藏起来一、填充合并单元格在工作表…

当你女朋友向你索吻的时候。。

1 当你女朋友向你索吻的时候。。2 可把我厉害坏了,叉会腰!3 这脸大的,超想捏4 网友制作的饭团,拍个照都怕打扰他的美梦5 有些话我嘴上不说,但希望你心里有数!6 这是一道很神奇的计算题。。你点的每个赞&…

C#后台,执行前台js 脚本

ClientScript.RegisterStartupScript(this.GetType(), "mb", "alert(\"提交成功\");window.location.href\"datadict.aspx\";", true); 转载于:https://www.cnblogs.com/xmyy/articles/2145635.html

heartbeat 日志分析

May 05 15:06:43 ckl-bd2 heartbeat:[21548]: info: Link ckl-bd2:eth0 up. #eth0为upMay 05 15:08:44 ckl-bd2 heartbeat:[21548]: WARN: node ckl-bd1: is dead #节点ckl-bd1为deadMay 05 15:08:44 ckl-bd2 heartbeat:[21548]: info: Comm_now_up(): updating status to ac…

python根据地址查看变量名_tensorflow创建变量以及根据名称查找变量

环境:Ubuntu14.04,tensorflow1.4(bazel源码安装),Anaconda python3.6声明变量主要有两种方法:tf.Variable和 tf.get_variable,二者的最大区别是:(1) tf.Variable是一个类,自带很多属性函数&…

要来吗,不错的WPF技术交流群!(大批干货今日自取)

欢迎加入我的编程技术交流群今日分享:1 《WPF-微软官方文档》2 《WPF客户端应用系统开发实战》全集3 《2021秋招WPF高频面试题-附答案》欢迎加入我的编程技术交流群MVP答疑解惑超多技术干货免费获取优质岗位和技术兼职内推和数百.NET/WPF 开发者一起进阶众多资料今…