第一节:复习委托,并且通过委托的异步调用开启一个新线程和异步回调、异步等待

一. 再谈委托

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         }

复制代码

结果:

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

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

相关文章

linux 修改 java 内存_Linux 和 Windows修改Java虚拟机内存大小

因为内存溢出问题1. Linux下直接修改%tomcat_home%/bin/catalina.sh文件在注释下紧接一行也就是脚本正文开始之前 加上Java_OPTS-server -Xms512m -Xmx1024m -XX:PermSize128m -XX:MaxPermSize512m如果报-x没有定义,则用declare -x JAVA_OPTS"-Xms512m -Xmx1024"初始…

第二节:深入剖析Thread的五大方法、数据槽、内存栅栏

一. Thread及其五大方法 Thread是.Net最早的多线程处理方式&#xff0c;它出现在.Net1.0时代&#xff0c;虽然现在已逐渐被微软所抛弃&#xff0c;微软强烈推荐使用Task(后面章节介绍)&#xff0c;但从多线程完整性的角度上来说&#xff0c;我们有必要了解下N年前多线程的是怎么…

java redis 生成唯一id_Redis在集群环境中生成唯一ID

概述设计目标&#xff1a;每秒最大生成10万个ID&#xff0c;ID单调递增且唯一。Reidis可以不需要持久化ID。要求:集群时钟不能倒退。总体思路&#xff1a;集群中每个节点预生成生成ID&#xff1b;然后与redis的已经存在的ID做比较。如果大于&#xff0c;则取节点生成的ID&#…

java await signal_【Java并发008】原理层面:ReentrantLock中 await()、signal()/signalAll()全解析...

一、前言上篇的文章中我们介绍了AQS源码中lock方法和unlock方法&#xff0c;这两个方法主要是用来解决并发中互斥的问题&#xff0c;这篇文章我们主要介绍AQS中用来解决线程同步问题的await方法、signal方法和signalAll方法&#xff0c;这几个方法主要对应的是synchronized中的…

第八节:Task的各类TaskTResult返回值以及通用线程的异常处理方案

一. Task的各种返回值-Task<TResult> PS&#xff1a; 在前面章节&#xff0c;我们介绍了Task类开启线程、线程等待、线程延续的方式&#xff0c;但我们并没有关注这些方式的返回值&#xff0c;其实他们都是有返回值的Task<TResult>&#xff0c;然后可以通过Task的…

mysql2005触发器修改成绩_创建、更改和删除触发器

创建、更改和删除触发器Creating, Altering, and Removing Triggers08/06/2017本文内容适用于&#xff1a;Applies to: SQL ServerSQL Server(所有支持的版本)SQL ServerSQL Server (all supported versions) Azure SQL 数据库Azure SQL DatabaseAzure SQL 数据库Azure SQL Dat…

第一节:从面向对象思想(oo)开发、接口、抽象类以及二者比较

一. 面向对象思想 1. 面向过程&#xff08;OP&#xff09;和面向对象&#xff08;OO&#xff09;的区别&#xff1a; (1)&#xff1a;面向过程就是排着用最简单的代码一步一步写下去&#xff0c;没有封装&#xff0c;当业务复杂的时候&#xff0c;改动就很麻烦了 (2)&#xff…

第二节:重写(new)、覆写(overwrite)、和重载(overload)

一. 重写 1. 关键字&#xff1a;new 2. 含义&#xff1a;子类继承父类中的普通方法&#xff0c;如果在子类中重写了一个和父类中完全相同的方法&#xff0c;子类中会报警告(问是否显式的隐藏父类的中的方法)&#xff0c;如果在子类中的方法前加上new关键字&#xff0c;则警告…

java 分页查询_JavaWeb之分页查询

时间&#xff1a;2016-12-11 01:411、分页的优点&#xff1a;只查询一页&#xff0c;不需要查询所有数据&#xff0c;能够提高效率。2、分页数据页面的数据都是由Servlet传递的* 当前页&#xff1a;pageCode> 如果页面没有向Servlet传递页码&#xff0c;那么Servlet默认…

第三节:深度剖析各类数据结构(Array、List、Queue、Stack)及线程安全问题和yeild关键字

一. 各类数据结构比较及其线程安全问题 1. Array(数组)&#xff1a; 分配在连续内存中,不能随意扩展&#xff0c;数组中数值类型必须是一致的。数组的声明有两种形式&#xff1a;直接定义长度&#xff0c;然后赋值&#xff1b;直接赋值。 缺点&#xff1a;插入数据慢。 优点&a…

第四节:IO、序列化和反序列化、加密解密技术

一. IO读写   这里主要包括文件的读、写、移动、复制、删除、文件夹的创建、文件夹的删除等常规操作。 注意&#xff1a;这里需要特别注意&#xff0c;对于普通的控制台程序和Web程序&#xff0c;将"相对路径"转换成"绝对路径"的方法不一致。 (1). 在w…

java mediator_java—mediator中介模式

中介者模式是由GoF提出的23种软件设计模式的一种。Mediator模式是行为模式之一&#xff0c;Mediator模式定义:用一个中介者对象来封装一系列的对象交互。中介者使各对象不需要显式的相互引用&#xff0c;从而使其耦合松散&#xff0c;而且可以独立的改变他们之间的交互。适用性…

第五节:泛型(泛型类、接口、方法、委托、泛型约束、泛型缓存、逆变和协变)

一. 泛型诞生的背景 在介绍背景之前&#xff0c;先来看一个案例&#xff0c;要求&#xff1a;分别输出实体model1、model2、model3的id和name值,这三个实体有相同的属性名字id和name。 1 public class myUtils2 {3 //要求&#xff1a;分别输出实体model1、model2、…

第六节:反射(几种写法、好处和弊端、利用反射实现IOC)

一. 加载dll,读取相关信息 1. 加载程序集的三种方式 调用Assembly类下的三个方法&#xff1a;Load、LoadFile、LoadFrom。 1       //1.1 Load方法&#xff1a;动态默认加载当前路径下的(bin)下的dll文件,不需要后缀 2 Assembly assembly Assembly.Load(&…

第七节:语法总结(1)(自动属性、out参数、对象初始化器、var和dynamic等)

一. 语法糖简介 语法糖也译为糖衣语法&#xff0c;是由英国计算机科学家彼得约翰兰达&#xff08;Peter J. Landin&#xff09;发明的一个术语&#xff0c;指计算机语言中添加的某种语法&#xff0c;这种语法对语言的功能并没有影响&#xff0c;但是更方便程序员使用。通常来说…

java不用插件播放媒体文件_java servlet不用插件上传文件:

展开全部import java.net.*;import java.io.*;import java.util.*;import javax.servlet.*;import javax.servlet.http.*;public class SaveFileServlet extends HttpServlet{FileWriter savefile;String filename null;String value null;/*** Handles a POST request*/publ…

第八节:语法总结(2)(匿名类、匿名方法、扩展方法)

一. 匿名类 1. 传统的方式给类赋值&#xff0c;需要先建一个实体类→实例化→赋值&#xff0c;步骤很繁琐&#xff0c;在.Net 3.0时代&#xff0c;微软引入匿名类的概念&#xff0c;简化了代码编写&#xff0c;提高了开发效率。 匿名类的声明语法&#xff1a; var objnew {字段…

第九节:委托和事件(1)(委托的发展历史、插件式编程、多播委托)

一. 委托的发展历史和基本用法 说起委托&#xff0c;每个人可能都会对他有不同的理解&#xff0c;结合实战中委托的使用&#xff0c;我对其理解是&#xff1a;委托和类一样&#xff0c;是用户的一个自定义类型&#xff0c;委托可以有参数、有返回值&#xff0c;委托的关键字是d…

第十节:委托和事件(2)(泛型委托、Func和Action、事件及与委托的比较)

一. 泛型委托 所谓的泛型委托&#xff0c;即自定义委托的参数可以用泛型约束&#xff0c;同时内置委托Func和Action本身就是泛型委托。 将上一个章节中的Calculator类中的方法用自定义泛型委托重新实现一下。 1 public class Calculator22 {3 //传统解决方案一&am…

java+sm4+加密算法_SM4加密算法实现Java和C#相互加密解密

https://www.cnblogs.com/miaoziblog/p/9040473.html近期由于项目需要使用SM4对数据进行加密&#xff0c;然后传给Java后台&#xff0c;Java后台使用的也是SM4的加密算法但是就是解密不正确&#xff0c;经过一步步调试发现Java中好多数据类型与C#的相同的数据类型是存在不同的比…