第一节:复习委托,并且通过委托的异步调用开启一个新线程和异步回调、异步等待。
一. 再谈委托
1. 委托是一个关键字为delegate的自定义类型,通过委托可以把方法以参数的形式传递给另外一个方法,实现插件式的开发模式;
同时调用委托的时候,委托所包含的所有方法都会被实现。
2. 委托的发展历史:new实例化传递方法→直接等于方法名→delegate匿名方法→省略delegate→省略括号中的参数→当只有一个参数省略小括号
→当方法体只有一行,省略大括号
(详见:http://www.cnblogs.com/yaopengfei/p/6959141.html)
3:常用的Action委托和Func委托
A. Action<>委托,无返回值,至少有一个参数的委托
B. Func<>委托,有返回值,可以无参数的委托(当然也可以有参数)
C. Action委托,无参数无返回值的委托
二. 委托的调用
委托的调用分为两种:
A. 同步调用:Invoke方法,方法参数为函数的参数。
B. 异步调用:BeginInvoke方法。
其中无论是哪类调用,都有两类写法:
①:利用Action<>(或Func<>)内置委托,调用的时候赋值。
②:利用Action委托,直接赋值,然后调用。
1 /// <summary>2 /// 执行动作:耗时而已3 /// </summary>4 private void TestThread2(string threadName1, string threadName2)5 {6 Console.WriteLine("线程开始:线程名为:{2}和{3},当前线程的id为:{0},当前时间为:{1},", System.Threading.Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff"), threadName1, threadName2);7 long sum = 0;8 for (int i = 1; i < 999999999; i++)9 {
10 sum += i;
11 }
12 Console.WriteLine("线程结束:线程名为:{2}和{3},当前线程的id为::{0},当前时间为:{1}", System.Threading.Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff"), threadName1, threadName2);
13 }
三. 深入剖析BeginInvoke方法
首先需要明确,该方法参数个数不定, 最后两个参数含义固定,如果不使用的话,需要赋值null;该方法最少两个参数,即方法无参数,这种情况下BeginInvoke中只有两个参数。此外,赋值的方法有几个参数,BeginInvoke中从左开始,新增几个参数。
①. 倒数第二个参数:是有一个参数值无返回值的委托,它代表的含义为,该线程执行完毕后的回调。
②. 倒数第一个参数:向倒数第二个参数(即回调)中传值,需要用AsyncState来接受。
③. 其它参数:即为赋值方法的参数。
注:BeginInvoke的返回值等价于异步回调中的t。
1 private void button13_Click(object sender, EventArgs e)2 {3 Stopwatch watch = new Stopwatch();4 watch.Start();5 Console.WriteLine("----------------- button1_Click 开始 主线程id为:{0} --------------------------", Thread.CurrentThread.ManagedThreadId);6 7 Action<string> myFunc = this.TestThread;8 IAsyncResult asyncResult = null;9 //参数说明:前面几个参数都是方法的参数值,倒数第二个为异步调用的回调函数,倒数第一个为传给回调函数的参数
10 for (int i = 0; i < 1; i++)
11 {
12 string name = string.Format("button1_Click{0}", i);
13 asyncResult = myFunc.BeginInvoke(name, t =>
14 {
15 Console.WriteLine("我是线程{0}的回调", Thread.CurrentThread.ManagedThreadId);
16 //用 t.AsyncState 来获取回调传进来的参数
17 Console.WriteLine("传进来的参数为:{0}", t.AsyncState);
18
19 //测试一下异步返回值的结果
20 Console.WriteLine("异步返回值的结果:{0}", t.Equals(asyncResult));
21 }, "maru");
22 }
23
24 watch.Stop();
25 Console.WriteLine("----------------- button1_Click 结束 主线程id为:{0} 总耗时:{1}--------------------------", Thread.CurrentThread.ManagedThreadId, watch.ElapsedMilliseconds);
26
27 }
结果:
四. 线程等待的三种方式
1. asyncResult.IsCompleted属性,该方式会存在时间上的误差。
2. WaitOne方法,可以控制一直等待or超时不再等待。
3. EndInvoke方法,官方推荐的线程等待的方式。
以上三种方式的局限性:批量线程等待的时候,不灵活,需要for循环了。
1 private void button14_Click(object sender, EventArgs e)2 {3 Stopwatch watch = new Stopwatch();4 watch.Start();5 Console.WriteLine("----------------- button1_Click 开始 主线程id为:{0} --------------------------", Thread.CurrentThread.ManagedThreadId);6 7 IAsyncResult asyncResult = null;8 Action<string> myFunc = this.TestThread;9 string name = string.Format("button1_Click{0}", 111);
10 asyncResult = myFunc.BeginInvoke(name, t =>
11 {
12 Console.WriteLine("我是线程{0}的回调", Thread.CurrentThread.ManagedThreadId);
13 //用 t.AsyncState 来获取回调传进来的参数
14 Console.WriteLine("传进来的参数为:{0}", t.AsyncState);
15 }, "maru");
16
17 //等待的方式1:会有时间上的误差
18 //while (!asyncResult.IsCompleted)
19 //{
20 // Console.WriteLine("正在等待中");
21 //}
22
23 // 等待的方式二:
24 //asyncResult.AsyncWaitHandle.WaitOne();//一直等待
25 //asyncResult.AsyncWaitHandle.WaitOne(-1);//一直等待
26 //asyncResult.AsyncWaitHandle.WaitOne(1000);//等待1000毫秒,超时就不等待了
27
28 //等待的方式三:
29 myFunc.EndInvoke(asyncResult);
30
31 watch.Stop();
32 Console.WriteLine("----------------- button1_Click 结束 主线程id为:{0} 总耗时:{1}--------------------------", Thread.CurrentThread.ManagedThreadId, watch.ElapsedMilliseconds);
33
34 }
下面是多个线程等待的情况:
1 private void button15_Click(object sender, EventArgs e)2 {3 Stopwatch watch = new Stopwatch();4 watch.Start();5 Console.WriteLine("----------------- button1_Click 开始 主线程id为:{0} --------------------------", Thread.CurrentThread.ManagedThreadId);6 7 List<IAsyncResult> list = new List<IAsyncResult>();8 9 for (int i = 0; i < 5; i++)
10 {
11 string name = string.Format("button1_Click{0}", i);
12 Action myFunc = () =>
13 {
14 TestThread2(name, name);
15 };
16 var asyncResult = myFunc.BeginInvoke(null, null);
17 list.Add(asyncResult);
18 }
19
20 //下面是线程等待
21 foreach (var item in list)
22 {
23 item.AsyncWaitHandle.WaitOne(-1);
24 }
25
26 watch.Stop();
27 Console.WriteLine("----------------- button1_Click 结束 主线程id为:{0} 总耗时:{1}--------------------------", Thread.CurrentThread.ManagedThreadId, watch.ElapsedMilliseconds);
28 }
结果:
第一节:复习委托,并且通过委托的异步调用开启一个新线程和异步回调、异步等待。相关推荐
- 第一节:复习委托,并且通过委托的异步调用开启一个新线程和异步回调、异步等待
一. 再谈委托 1. 委托是一个关键字为delegate的自定义类型,通过委托可以把方法以参数的形式传递给另外一个方法,实现插件式的开发模式: 同时调用委托的时候,委托所包含的所有方法都会被实现. 2 ...
- 那些年我们一起追逐的多线程(Thread、ThreadPool、委托异步调用、Task/TaskFactory、Parallerl、async和await)
一. 背景 在刚接触开发的头几年里,说实话,根本不考虑多线程的这个问题,貌似那时候脑子里也有没有多线程的这个概念,所有的业务都是一个线程来处理,不考虑性能问题,当然也没有考虑多线程操作一条记录存在的并 ...
- C# 委托高级应用----线程——创建无阻塞的异步调用(一)
前言 本文大部分内容来自于mikeperetz的Asynchronous Method Invocation及本人的一些个人体会所得,希望对你有所帮助.原英文文献可以在codeproject中搜索到. ...
- 如何让人大致理解RxJava思想:第一节 初步理解RxJava
如何让人大致理解RxJava思想:第一节 初步理解RxJava 首先,我们需要明确,一个人不可能一口气吃成一个胖子,你不可能仅仅花5分钟看完我这篇文章,然后一拍桌子,大叫一声,我知道了,然后赢取白富美 ...
- 设计模式-02.经典设计原则-第一节-单一职责原则,开闭原则,里式替换,接口隔离【万字长文系列】
文章目录 设计模式经典设计原则-第一节 单一职责原则(SRP) 如何理解单一职责原则? 如何判断类的职责是否足够单一? 类的职责是否设计得越单一越好? 开闭原则(OCP) 如何理解"对扩展开 ...
- [转]VS2010 教程:创建一个 WPF 应用程序 (第一节)
[转]VS2010 教程:创建一个 WPF 应用程序 (第一节) http://msdn.microsoft.com/zh-cn/ff629048(zh-cn) Extended WPF Toolki ...
- Flash AS入门教程:影片剪辑第一节创建影片剪辑
本例继续讲解AS的基础知识,今天我们来学习Flash AS入门系列教程第七课:影片剪辑第一节创建影片剪辑~~ 影片剪辑 影片剪辑就象一个独立的swf一样,运行时不受主时间轴的限制,它有它自已的时间轴. ...
- 第一章C#高级特性 C#委托
一.委托的概述与声明 委托:类型化的函数指针 它的使用场景是:将方法作为参数进行传递 1.委托是一种引用数据类型(object,数组,string,class这些都是引用类型) 扩展: 程序设计之一: ...
- C# 关于委托和事件的妙文:通过一个例子详细介绍委托和事件的作用;Observer模式简介...
委托和事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易.它们就像是一道槛儿,过了这个槛的人,觉得真是太容易了,而没有过去的人每次见 ...
最新文章
- 也谈子网划分和子网通信
- 我狂揽16个offer:面试常问的这些问题你准备了吗?
- mysql字符串等于失效_MySql整型索引和字符串索引失效或隐式转换问题
- 静态路由和DHCP/NAT/VLAN的配置实例
- 数据治理将遇到哪些问题
- gridview的sort_GRIDVIEW排序的方法
- 前端实现登录时记住密码功能
- css 图片放大1.2倍,二倍图以及背景图缩放
- 记录一次opper R9s Plus 从发现循环重启到解决的过程
- 通过浏览器geolocation属性获取经度和纬度(1)
- 面试案例-String Interpolation的实现(Java实现)
- 有人问“一花一世界,一叶一菩提”
- selenium——爬取qq空间说说
- 优动漫PAINT是什么?有哪些功能和特色
- iPhone 中常用、好用的提醒类软件(闹钟、提醒事项、日历、滴答清单)
- arduino+ESP8266网络控制LED灯
- 头一回见!提升10倍效率,阿里给业务校验平台插上了AI的翅膀
- 倩女幽魂 易语言模块 - 附: 自动打怪吃药 辅助 外挂,永不过期!【已有新版】
- 开发工具界面没了,但是后台进程还在跑,怎么找回来
- 可视库位电子纸广泛应用仓储管理
热门文章
- Python全栈开发——面向对象的三大特性(继承 多态 封装)
- 深入理解Spring Redis的使用 (五)、常见问题汇总
- 第二十四章——文件管理的代码保存
- CSS display属性的值及作用
- IOS 修改UIAlertController的按钮标题的字体颜色,字号,内容
- ConfigurationManager.AppSettings[] ConfigurationManager智能显示不出来
- 818. Race Car
- leetcode之回溯backtracing专题1
- [Leetcode][第459题][JAVA][重复的字符串][子串][匹配]
- 【数据结构与算法】二叉树