1. 1 历程、应用程序域与线程的涉及,更应当多留意I/O线程的操作

引言

一 、线程的概念

本文重要从线程的根底用法,CL纳瓦拉线程池当福建中华工程集团笔者线程与I/O线程的支出,并行操作PLINQ等三个方面介绍多线程的开支。
当中央委员托的BeginInvoke方法以及回调函数最为常用。 而
I/O线程或者简单受到大家的忽视,其实在支付十二线程系统,更应当多留意I/O线程的操作。尤其是在ASP.NET开发个中,大概越来越多人只会注目的在于客户端采纳Ajax只怕在劳务器端使用UpdatePanel。其实合情合理施用I/O线程在通信项目或文件下载时,能尽恐怕地缩短IIS的下压力。
并行编制程序是Framework4.0中奋力推广的异步操作办法,更值得更深远地上学。
希望本篇小说能对各位的上学钻研有着帮忙,在那之中有所错漏的地点敬请点评。

 1. 1 进程、应用程序域与线程的关系

 

进度(Process)是Windows系统中的2个基本概念,它涵盖着二个运作程序所供给的财富。进度之间是相持独立的,一个进程无法访问另三个进度的数码(除非动用分布式计算格局),贰个经过运维的败诉也不会影响此外进度的周转,Windows系统正是使用进程把工作划分为八个独立的区域的。进度能够知晓为七个顺序的主干边界。

 

利用程序域(AppDomain)是叁个程序运维的逻辑区域,它能够算得多少个轻量级的经过,.NET的次序集就是在运用程序域中运作的,1个进度能够分包有多少个使用程序域,贰个应用程序域也得以分包八个程序集。在二个利用程序域中蕴涵了三个或七个左右文context,使用前后文CL福特Explorer就能够把一些特殊指标的意况放置在分歧容器当中。

目录

线程(Thread)是经过中的基本举办单元,在经过入口实施的首先个线程被视为那些进程的主线程。在.NET应用程序中,都是以Main()方法作为入口的,当调用此措施时系统就会活动创设1个主线程。线程重假使由CPU寄存器、调用栈和线程本地存款和储蓄器(Thread
Local
Storage,TLS)组成的。CPU寄存器首要记录当前所推行线程的事态,调用栈主要用于维护线程所调用到的内存与数量,TLS首要用来存放线程的动静新闻。

壹 、线程的定义

进度、应用程序域、线程的涉及如下图,1个进度内得以回顾七个利用程序域,也有包蕴八个线程,线程也能够穿梭于五个使用程序域在那之中。但在同三个随时,线程只会处于八个利用程序域内。

二 、线程的基础知识

 

③ 、以ThreadStart情势达成八线程

亿万先生: 1

④ 、CL揽胜极光线程池的工作者线程

 
由于本文是以介绍二十八线程技术为宗旨,对进度、应用程序域的介绍就到此甘休。关于进度、线程、应用程序域的技艺,在“C#归纳揭秘——细说进度、应用程序域与上下文”会有详尽介绍。

伍 、CLXC90线程池的I/O线程

 

六、异步
SqlCommand

1.2 多线程

7、并行编制程序与PLINQ

在单CPU系统的三个单位时间(time
slice)内,CPU只好运转单个线程,运维顺序取决于线程的先期级别。若是在单位时间内线程未能做到实施,系统就会把线程的事态消息保存到线程的本土存储器(TLS)
中,以便下次执行时上涨执行。而三十二线程只是系统带来的二个假像,它在三个单位时间内开展四个线程的切换。因为切换频密而且单位时间相当短暂,所以多线程可被看成同时运转。

捌 、计时器与锁

适宜使用三十二线程能增长系统的品质,比如:在系统请求大容积的数量时利用八线程,把数量输出工作付出异步线程,使主线程保持其安居去处理其余题材。但要求留意一点,因为CPU须求成本不少的年华在线程的切换上,所以重重地选择多线程反而会导致质量的下落。

 

 

 

归来目录

 

② 、线程的基础知识

 

2.1 System.Threading.Thread类

一 、线程的概念

System.Threading.Thread是用来控制线程的底子类,通过Thread能够操纵当前接纳程序域中线程的创制、挂起、结束、销毁。

 1. 1 历程、应用程序域与线程的涉及

它归纳以下常用公共性质:

经过(Process)是Windows系统中的三个基本概念,它含有着二个运维程序所急需的能源。进度之间是周旋独立的,二个经过不能访问另叁个经过的多寡(除非动用分布式总计格局),多个历程运维的退步也不会影响其余进度的运行,Windows系统就是利用进度把工作划分为三个独立的区域的。进程能够领略为多个主次的主导边界。

属性名称 说明
CurrentContext 获取线程正在其中执行的当前上下文。
CurrentThread 获取当前正在运行的线程。
ExecutionContext 获取一个 ExecutionContext 对象,该对象包含有关当前线程的各种上下文的信息。
IsAlive 获取一个值,该值指示当前线程的执行状态。
IsBackground 获取或设置一个值,该值指示某个线程是否为后台线程。
IsThreadPoolThread 获取一个值,该值指示线程是否属于托管线程池。
ManagedThreadId 获取当前托管线程的唯一标识符。
Name 获取或设置线程的名称。
Priority 获取或设置一个值,该值指示线程的调度优先级。
ThreadState 获取一个值,该值包含当前线程的状态。

选拔程序域(AppDomain)是三个程序运营的逻辑区域,它可以说是1个轻量级的历程,.NET的主次集正是在动用程序域中运营的,三个经过能够分包有七个应用程序域,三个施用程序域也足以涵盖三个程序集。在贰个行使程序域中带有了一个或多少个上下文context,使用前后文CL库罗德就可见把某个特殊指标的状态放置在分歧容器当中。

 

线程(Thread)是经过中的基本举行单元,在进程入口实施的第①个线程被视为那个进程的主线程。在.NET应用程序中,都以以Main()方法作为入口的,当调用此办法时系统就会自行创造一个主线程。线程首如若由CPU寄存器、调用栈和线程本地存款和储蓄器(Thread
Local
Storage,TLS)组成的。CPU寄存器首要记录当前所推行线程的场所,调用栈首要用以保险线程所调用到的内部存款和储蓄器与数量,TLS首要用来存放线程的气象新闻。

2.1.1 线程的标识符

进度、应用程序域、线程的关联如下图,3个进度内足以归纳八个使用程序域,也有包蕴多少个线程,线程也得以持续于八个应用程序域其中。但在同一个随时,线程只会处在一个行使程序域内。

ManagedThreadId是认可线程的绝无仅有标识符,程序在多数情景下都以通过Thread.ManagedThreadId来分辨线程的。而Name是贰个可变值,在默许时候,Name为叁个空值
Null,开发职员能够因此程序设置线程的名目,但那只是二个扶持功效。

 

 

亿万先生: 2

2.1.2 线程的预先级别

 
由于本文是以介绍多线程技术为大旨,对经过、应用程序域的介绍就到此截至。关于进度、线程、应用程序域的技术,在“C#归纳揭秘——细说进度、应用程序域与上下文”会有详实介绍。

.NET为线程设置了Priority属性来定义线程执行的先行级别,里面含有两个选取,在这之中Normal是暗中认可值。除非系统有特殊供给,不然不应有随便设置线程的预先级别。

 

成员名称 说明
Lowest 可以将 Thread 安排在具有任何其他优先级的线程之后。
BelowNormal 可以将 Thread 安排在具有 Normal 优先级的线程之后,在具有 Lowest 优先级的线程之前。
Normal 默认选择。可以将 Thread 安排在具有 AboveNormal 优先级的线程之后,在具有BelowNormal 优先级的线程之前。
AboveNormal 可以将 Thread 安排在具有 Highest 优先级的线程之后,在具有 Normal 优先级的线程之前。
Highest 可以将 Thread 安排在具有任何其他优先级的线程之前。

1.2 多线程

 

在单CPU系统的三个单位时间(time
slice)内,CPU只好运营单个线程,运转顺序取决于线程的优先级别。若是在单位时间内线程未能成功实施,系统就会把线程的意况音讯保存到线程的当地存储器(TLS)
中,以便下次执行时上涨执行。而二十二十四线程只是系统带来的二个假像,它在多个单位时间内展开多少个线程的切换。因为切换频密而且单位时间非常短暂,所以二十四线程可被看成同时运转。

2.1.3 线程的景况

合适采纳二十四线程能增高系统的天性,比如:在系统请求大体积的多寡时采纳二十四线程,把多少输出工作付出异步线程,使主线程保持其稳定去处理别的题材。但需求专注一点,因为CPU需求开销不少的小时在线程的切换上,所以众多地采取四线程反而会导致品质的减退。

透过ThreadState能够检查和测试线程是处在Unstarted、Sleeping、Running
等等状态,它比 IsAlive 属质量提供越多的特定音信。

 

前边说过,多个采取程序域中或许包蕴多个上下文,而经过CurrentContext能够得到线程当前的上下文。

回来目录

CurrentThread是最常用的壹本质量,它是用以获取当前运作的线程。

二 、线程的基础知识

 

2.1 System.Threading.Thread类

2.1.4 System.Threading.Thread的方法

System.Threading.Thread是用来控制线程的基本功类,通过Thread能够决定当前应用程序域中线程的创办、挂起、结束、销毁。

Thread
中包括了七个办法来支配线程的创设、挂起、甘休、销毁,今后来的例证中会日常应用。

它归纳以下常用公共性质:

方法名称 说明
Abort()     终止本线程。
GetDomain() 返回当前线程正在其中运行的当前域。
GetDomainId() 返回当前线程正在其中运行的当前域Id。
Interrupt() 中断处于 WaitSleepJoin 线程状态的线程。
Join() 已重载。 阻塞调用线程,直到某个线程终止时为止。
Resume() 继续运行已挂起的线程。
Start()   执行本线程。
Suspend() 挂起当前线程,如果当前线程已属于挂起状态则此不起作用
Sleep()   把正在运行的线程挂起一段时间。
属性名称 说明
CurrentContext 获取线程正在其中执行的当前上下文。
CurrentThread 获取当前正在运行的线程。
ExecutionContext 获取一个 ExecutionContext 对象,该对象包含有关当前线程的各种上下文的信息。
IsAlive 获取一个值,该值指示当前线程的执行状态。
IsBackground 获取或设置一个值,该值指示某个线程是否为后台线程。
IsThreadPoolThread 获取一个值,该值指示线程是否属于托管线程池。
ManagedThreadId 获取当前托管线程的唯一标识符。
Name 获取或设置线程的名称。
Priority 获取或设置一个值,该值指示线程的调度优先级。
ThreadState 获取一个值,该值包含当前线程的状态。

 

 

2.1.5 开发实例

2.1.1 线程的标识符

以下那些例子,即是通过Thread突显当前线程信息

ManagedThreadId是承认线程的唯一标识符,程序在当先1/2处境下都以透过Thread.ManagedThreadId来识别线程的。而Name是2个可变值,在暗许时候,Name为贰个空值
Null,开发人士能够经进度序设置线程的称呼,但那只是二个援救效能。

亿万先生: 3

 

 1         static void Main(string[] args)
 2         {
 3             Thread thread = Thread.CurrentThread;
 4             thread.Name = "Main Thread";
 5             string threadMessage = string.Format("Thread ID:{0}\n    Current AppDomainId:{1}\n    "+
 6                 "Current ContextId:{2}\n    Thread Name:{3}\n    "+
 7                 "Thread State:{4}\n    Thread Priority:{5}\n",
 8                 thread.ManagedThreadId, Thread.GetDomainID(), Thread.CurrentContext.ContextID,
 9                 thread.Name, thread.ThreadState, thread.Priority);
10             Console.WriteLine(threadMessage);
11             Console.ReadKey();
12         }

2.1.2 线程的事先级别

亿万先生: 4

.NET为线程设置了Priority属性来定义线程执行的预先级别,里面含有两个选项,个中Normal是暗中认可值。除非系统有特殊必要,不然不应当随便设置线程的预先级别。

 

成员名称 说明
Lowest 可以将 Thread 安排在具有任何其他优先级的线程之后。      
BelowNormal 可以将 Thread 安排在具有 Normal 优先级的线程之后,在具有 Lowest 优先级的线程之前。      
Normal 默认选择。可以将 Thread 安排在具有 AboveNormal 优先级的线程之后,在具有 BelowNormal 优先级的线程之前。 
AboveNormal 可以将 Thread 安排在具有 Highest 优先级的线程之后,在具有 Normal 优先级的线程之前。      
Highest 可以将 Thread 安排在具有任何其他优先级的线程之前。      

运营结果

 

亿万先生: 5

2.1.3 线程的情况

 

通过ThreadState能够检查和测试线程是处在Unstarted、Sleeping、Running
等等状态,它比 IsAlive 属质量提供更多的一定消息。

2.2  System.Threading 命名空间

前边说过,一个运用程序域中大概包蕴多个上下文,而因此CurrentContext能够拿走线程当前的上下文。

在System.Threading命名空间内提供多少个艺术来创设八线程应用程序,当中ThreadPool与Thread是三十二线程开发中最常用到的,在.NET中特地设定了3个CL奇骏线程池专门用来管理线程的运作,这么些CL奥德赛线程池就是经过ThreadPool类来保管。而Thread是管理线程的最间接格局,下边几节将详细介绍有关内容。

CurrentThread是最常用的两特性子,它是用于获取当前运作的线程。

类     说明
AutoResetEvent 通知正在等待的线程已发生事件。无法继承此类。
ExecutionContext 管理当前线程的执行上下文。无法继承此类。
Interlocked 为多个线程共享的变量提供原子操作。
Monitor 提供同步对对象的访问的机制。
Mutex 一个同步基元,也可用于进程间同步。
Thread 创建并控制线程,设置其优先级并获取其状态。
ThreadAbortException 在对 Abort 方法进行调用时引发的异常。无法继承此类。
ThreadPool 提供一个线程池,该线程池可用于发送工作项、处理异步 I/O、代表其他线程等待以及处理计时器。
Timeout 包含用于指定无限长的时间的常数。无法继承此类。
Timer 提供以指定的时间间隔执行方法的机制。无法继承此类。
WaitHandle 封装等待对共享资源的独占访问的操作系统特定的对象。

 

在System.Threading中的包蕴了下表中的八个常用委托,当中ThreadStart、ParameterizedThreadStart是最常用到的委托。
由ThreadStart生成的线程是最直白的措施,但由ThreadStart所生成并不受线程池管理。
而ParameterizedThreadStart是为异步触发带参数的格局而设的,在下一节将为大家逐一细说。

2.1.4 System.Threading.Thread的方法

委托 说明
ContextCallback 表示要在新上下文中调用的方法。
ParameterizedThreadStart 表示在 Thread 上执行的方法。
ThreadExceptionEventHandler 表示将要处理 Application 的 ThreadException 事件的方法。
ThreadStart 表示在 Thread 上执行的方法。
TimerCallback 表示处理来自 Timer 的调用的方法。
WaitCallback 表示线程池线程要执行的回调方法。
WaitOrTimerCallback 表示当 WaitHandle 超时或终止时要调用的方法。

Thread
中回顾了七个点子来决定线程的创办、挂起、结束、销毁,今后来的事例中会平日应用。

 

方法名称 说明
Abort()     终止本线程。
GetDomain() 返回当前线程正在其中运行的当前域。
GetDomainId() 返回当前线程正在其中运行的当前域Id。
Interrupt() 中断处于 WaitSleepJoin 线程状态的线程。
Join() 已重载。 阻塞调用线程,直到某个线程终止时为止。
Resume() 继续运行已挂起的线程。
Start()   执行本线程。
Suspend() 挂起当前线程,如果当前线程已属于挂起状态则此不起作用
Sleep()   把正在运行的线程挂起一段时间。

2.3 线程的管制艺术

 

经过ThreadStart来创设1个新线程是最直接的法子,但诸如此类成立出来的线程比较难管理,假诺创设过多的线程反而会让系统的品质下载。有见及此,.NET为线程管理特别设置了一个CLENCORE线程池,使用CLSportage线程池系统能够更客观地管理线程的施用。全部请求的劳务都能运作于线程池中,当运营截止时线程便会回归到线程池。通过安装,能控制线程池的最大线程数量,在呼吁超出线程最大值时,线程池能依照操作的先行级别来执行,让部分操作处于等候状态,待有线程回归时再实施操作。

2.1.5 开发实例

基础知识就为大家介绍到那里,上边将详细介绍多线程的开发。

以下那一个事例,就是通过Thread呈现当前线程音信

 

亿万先生: 6😉

 

 1         static void Main(string[] args)
 2         {
 3             Thread thread = Thread.CurrentThread;
 4             thread.Name = "Main Thread";
 5             string threadMessage = string.Format("Thread ID:{0}\n    Current AppDomainId:{1}\n    "+
 6                 "Current ContextId:{2}\n    Thread Name:{3}\n    "+
 7                 "Thread State:{4}\n    Thread Priority:{5}\n",
 8                 thread.ManagedThreadId, Thread.GetDomainID(), Thread.CurrentContext.ContextID,
 9                 thread.Name, thread.ThreadState, thread.Priority);
10             Console.WriteLine(threadMessage);
11             Console.ReadKey();
12         }

重临目录

亿万先生: 7😉

③ 、以ThreadStart格局完毕二十四线程

 

3.1 使用ThreadStart委托

运行结果

此间先以二个例证展现一下二十四线程带来的好处,首先在Message类中国建工业总会公司立一个方法ShowMessage(),里面展现了眼下运作线程的Id,并动用Thread.Sleep(int
)
方法模拟部分工作。在main()中经过ThreadStart委托绑定Message对象的ShowMessage()方法,然后通过Thread.Start()执行异步方法。

亿万先生: 8

亿万先生: 9

 

 1       public class Message
 2       {
 3           public void ShowMessage()
 4           {
 5               string message = string.Format("Async threadId is :{0}",
 6                                               Thread.CurrentThread.ManagedThreadId);
 7               Console.WriteLine(message);
 8   
 9               for (int n = 0; n < 10; n++)
10               {
11                   Thread.Sleep(300);   
12                   Console.WriteLine("The number is:" + n.ToString()); 
13               }
14           }
15       }
16   
17       class Program
18       {
19           static void Main(string[] args)
20           {
21               Console.WriteLine("Main threadId is:"+
22                                 Thread.CurrentThread.ManagedThreadId);
23               Message message=new Message();
24               Thread thread = new Thread(new ThreadStart(message.ShowMessage));
25               thread.Start();
26               Console.WriteLine("Do something ..........!");
27               Console.WriteLine("Main thread working is complete!");
28               
29           }
30       }

2.2  System.Threading 命名空间

亿万先生: 10

在System.Threading命名空间内提供多少个艺术来营造二十三十二线程应用程序,在那之中ThreadPool与Thread是八线程开发中最常用到的,在.NET中特意设定了多少个CLRAV4线程池专门用来管理线程的运作,这一个CLCRUISER线程池便是经过ThreadPool类来管理。而Thread是管制线程的最直白格局,上边几节将详细介绍有关内容。

请留心运营结果,在调用Thread.Start()方法后,系统以异步格局运转Message.ShowMessage(),而主线程的操作是继续执行的,在Message.ShowMessage()完毕前,主线程已形成有着的操作。

类     说明
AutoResetEvent 通知正在等待的线程已发生事件。无法继承此类。
ExecutionContext 管理当前线程的执行上下文。无法继承此类。
Interlocked 为多个线程共享的变量提供原子操作。
Monitor 提供同步对对象的访问的机制。
Mutex 一个同步基元,也可用于进程间同步。
Thread 创建并控制线程,设置其优先级并获取其状态。
ThreadAbortException 在对 Abort 方法进行调用时引发的异常。无法继承此类。
ThreadPool 提供一个线程池,该线程池可用于发送工作项、处理异步 I/O、代表其他线程等待以及处理计时器。
Timeout 包含用于指定无限长的时间的常数。无法继承此类。
Timer 提供以指定的时间间隔执行方法的机制。无法继承此类。
WaitHandle 封装等待对共享资源的独占访问的操作系统特定的对象。

亿万先生: 11

在System.Threading中的包罗了下表中的八个常用委托,在那之中ThreadStart、ParameterizedThreadStart是最常用到的信托。
由ThreadStart生成的线程是最直白的法子,但由ThreadStart所生成并不受线程池管理。
而ParameterizedThreadStart是为异步触发带参数的主意而设的,在下一节将为大家逐一细说。

 

委托 说明
ContextCallback 表示要在新上下文中调用的方法。
ParameterizedThreadStart 表示在 Thread 上执行的方法。
ThreadExceptionEventHandler 表示将要处理 Application 的 ThreadException 事件的方法。
ThreadStart 表示在 Thread 上执行的方法。
TimerCallback 表示处理来自 Timer 的调用的方法。
WaitCallback 表示线程池线程要执行的回调方法。
WaitOrTimerCallback 表示当 WaitHandle 超时或终止时要调用的方法。

3.2 使用ParameterizedThreadStart委托

 

ParameterizedThreadStart委托与ThreadStart委托相当相像,但ParameterizedThreadStart委托是面向带参数方法的。注意ParameterizedThreadStart
对应措施的参数为object,此参数能够为四个值对象,也可以为三个自定义对象。

2.3 线程的管理措施

亿万先生: 12

由此ThreadStart来创立1个新线程是最直接的办法,但这么创立出来的线程比较难管理,假如创制过多的线程反而会让系统的习性下载。有见及此,.NET为线程管理专门设置了二个CL酷威线程池,使用CLKuga线程池系统能够更合理地管理线程的运用。全部请求的劳务都能运作于线程池中,当运转甘休时线程便会回归到线程池。通过安装,能控制线程池的最大线程数量,在呼吁超出线程最大值时,线程池能遵照操作的事先级别来实施,让部分操作处于等候状态,待有线程回归时再进行操作。

 1     public class Person
 2     {
 3         public string Name
 4         {
 5             get;
 6             set;
 7         }
 8         public int Age
 9         {
10             get;
11             set;
12         }
13     }
14 
15     public class Message
16     {
17         public void ShowMessage(object person)
18         {
19             if (person != null)
20             {
21                 Person _person = (Person)person;
22                 string message = string.Format("\n{0}'s age is {1}!\nAsync threadId is:{2}",
23                     _person.Name,_person.Age,Thread.CurrentThread.ManagedThreadId);
24                 Console.WriteLine(message);
25             }
26             for (int n = 0; n < 10; n++)
27             {
28                 Thread.Sleep(300);   
29                 Console.WriteLine("The number is:" + n.ToString()); 
30             }
31         }
32     }
33 
34     class Program
35     {
36         static void Main(string[] args)
37         {     
38             Console.WriteLine("Main threadId is:"+Thread.CurrentThread.ManagedThreadId);
39             
40             Message message=new Message();
41             //绑定带参数的异步方法
42             Thread thread = new Thread(new ParameterizedThreadStart(message.ShowMessage));
43             Person person = new Person();
44             person.Name = "Jack";
45             person.Age = 21;
46             thread.Start(person);  //启动异步线程 
47             
48             Console.WriteLine("Do something ..........!");
49             Console.WriteLine("Main thread working is complete!");
50              
51         }
52     }

基础知识就为我们介绍到那里,下边将详细介绍八线程的开支。

亿万先生: 13

 

运转结果:

 

亿万先生: 14

重回目录

 

叁 、以ThreadStart格局完结八线程

3.3 前台线程与后台线程

3.1 使用ThreadStart委托

在意上述八个例证都并未运用Console.ReadKey(),但系统依旧会等待异步线程实现后才会终结。那是因为运用Thread.Start()运行的线程暗中认可为前台线程,而系统必须等待全部前台线程运转结束后,应用程序域才会自动卸载。

此处先以1个例证体现一下四线程带来的利益,首先在Message类中树立1个主意ShowMessage(),里面展现了当前运作线程的Id,并应用Thread.Sleep(int
)
方法模拟部分工作。在main()中经过ThreadStart委托绑定Message对象的ShowMessage()方法,然后经过Thread.Start()执行异步方法。

在第四节曾经介绍过线程Thread有叁特性质IsBackground,通过把此属性设置为true,就足以把线程设置为后台线程!那时应用程序域将在主线程完结时就被卸载,而不会等待异步线程的运维。

亿万先生: 15😉

 

 1       public class Message  2       {  3           public void ShowMessage()  4           {  5               string message = string.Format("Async threadId is :{0}",  6                                               Thread.CurrentThread.ManagedThreadId);  7               Console.WriteLine(message);  8     9               for (int n = 0; n < 10; n++) 10               { 11                   Thread.Sleep(300);    12                   Console.WriteLine("The number is:" + n.ToString());  13               } 14           } 15       } 16    17       class Program 18       { 19           static void Main(string[] args) 20           { 21               Console.WriteLine("Main threadId is:"+ 22                                 Thread.CurrentThread.ManagedThreadId); 23               Message message=new Message(); 24               Thread thread = new Thread(new ThreadStart(message.ShowMessage)); 25               thread.Start(); 26               Console.WriteLine("Do something ..........!"); 27               Console.WriteLine("Main thread working is complete!"); 28                29           } 30       }

3.4 挂起线程

亿万先生: 16😉

为了等待别的后台线程达成后再甘休主线程,就能够选取Thread.Sleep()方法。

请留意启动结果,在调用Thread.Start()方法后,系统以异步格局运维Message.ShowMessage(),而主线程的操作是继续执行的,在Message.ShowMessage()达成前,主线程已到位有着的操作。

亿万先生: 17

亿万先生: 18

 1     public class Message
 2     {
 3         public void ShowMessage()
 4         {
 5             string message = string.Format("\nAsync threadId is:{0}",
 6                                            Thread.CurrentThread.ManagedThreadId);
 7             Console.WriteLine(message);
 8             for (int n = 0; n < 10; n++)
 9             {
10                 Thread.Sleep(300);
11                 Console.WriteLine("The number is:" + n.ToString());
12             }
13         }
14     }
15 
16     class Program
17     {
18         static void Main(string[] args)
19         {     
20             Console.WriteLine("Main threadId is:"+
21                               Thread.CurrentThread.ManagedThreadId);
22             
23             Message message=new Message();
24             Thread thread = new Thread(new ThreadStart(message.ShowMessage));
25             thread.IsBackground = true;
26             thread.Start();
27             
28             Console.WriteLine("Do something ..........!");
29             Console.WriteLine("Main thread working is complete!");
30             Console.WriteLine("Main thread sleep!");
31             Thread.Sleep(5000);
32         }
33     }

 

亿万先生: 19

3.2 使用ParameterizedThreadStart委托

运作结果如下,此时应用程序域将在主线程运维5秒后活动终止

ParameterizedThreadStart委托与ThreadStart委托非常相似,但ParameterizedThreadStart委托是面向带参数方法的。注意ParameterizedThreadStart
对应措施的参数为object,此参数能够为贰个值对象,也能够为一个自定义对象。

亿万先生: 20

亿万先生: 21😉

 

 1     public class Person
 2     {
 3         public string Name
 4         {
 5             get;
 6             set;
 7         }
 8         public int Age
 9         {
10             get;
11             set;
12         }
13     }
14 
15     public class Message
16     {
17         public void ShowMessage(object person)
18         {
19             if (person != null)
20             {
21                 Person _person = (Person)person;
22                 string message = string.Format("\n{0}'s age is {1}!\nAsync threadId is:{2}",
23                     _person.Name,_person.Age,Thread.CurrentThread.ManagedThreadId);
24                 Console.WriteLine(message);
25             }
26             for (int n = 0; n < 10; n++)
27             {
28                 Thread.Sleep(300);   
29                 Console.WriteLine("The number is:" + n.ToString()); 
30             }
31         }
32     }
33 
34     class Program
35     {
36         static void Main(string[] args)
37         {     
38             Console.WriteLine("Main threadId is:"+Thread.CurrentThread.ManagedThreadId);
39             
40             Message message=new Message();
41             //绑定带参数的异步方法
42             Thread thread = new Thread(new ParameterizedThreadStart(message.ShowMessage));
43             Person person = new Person();
44             person.Name = "Jack";
45             person.Age = 21;
46             thread.Start(person);  //启动异步线程 
47             
48             Console.WriteLine("Do something ..........!");
49             Console.WriteLine("Main thread working is complete!");
50              
51         }
52     }

但系统不大概预感异步线程须要周转的时光,所以用经过Thread.Sleep(int)阻塞主线程并不是二个好的消除方法。有见及此,.NET专门为等候异步线程实现支付了另三个格局thread.Join()。把上边例子中的最终一行Thread.Sleep(四千)修改为
thread.Join() 就能保障主线程在异步线程thread运维甘休后才会终止。

亿万先生: 22😉

 

运营结果:

3.5 Suspend 与 Resume (慎用)

亿万先生: 23

Thread.Suspend()与 Thread.Resume()是在Framework1.0
就曾经存在的老艺术了,它们各自能够挂起、恢复生机线程。但在Framework2.0中就早已明显排斥那八个措施。那是因为只要有个别线程占用了已有的财富,再使用Suspend()使线程长时间处在挂起状态,当在别的线程调用这个能源的时候就会唤起死锁!所以在尚未须求的情事下应该防止接纳这多个法子。

 

 

3.3 前台线程与后台线程

3.6 终止线程

留意上述多个例证都不曾利用Console.ReadKey(),但系统仍然会等待异步线程实现后才会终止。那是因为使用Thread.Start()运维的线程暗中同意为前台线程,而系统必须等待全体前台线程运转结束后,应用程序域才会自行卸载。

若想终止正在运转的线程,能够动用Abort()方法。在选择Abort()的时候,将吸引贰个非同小可非凡ThreadAbortException 。
若想在线程终止前复苏线程的施行,能够在抓获相当后
,在catch(ThreadAbortException ex){…}
中调用Thread.ResetAbort()裁撤终止。
而采纳Thread.Join()能够保证应用程序域等待异步线程结束后才截止运维。

在第一节曾经介绍过线程Thread有二个属性IsBackground,通过把此属性设置为true,就可以把线程设置为后台线程!那时应用程序域将在主线程达成时就被卸载,而不会等待异步线程的运维。

亿万先生: 24

 

 1          static void Main(string[] args)
 2          {
 3              Console.WriteLine("Main threadId is:" +
 4                                Thread.CurrentThread.ManagedThreadId);
 5  
 6              Thread thread = new Thread(new ThreadStart(AsyncThread));
 7              thread.IsBackground = true;
 8              thread.Start();
 9              thread.Join();
10  
11          }     
12          
13          //以异步方式调用
14          static void AsyncThread()
15          {
16              try
17              {
18                  string message = string.Format("\nAsync threadId is:{0}",
19                     Thread.CurrentThread.ManagedThreadId);
20                  Console.WriteLine(message);
21  
22                  for (int n = 0; n < 10; n++)
23                  {
24                      //当n等于4时,终止线程
25                      if (n >= 4)
26                      {
27                          Thread.CurrentThread.Abort(n);
28                      }
29                      Thread.Sleep(300);
30                      Console.WriteLine("The number is:" + n.ToString());
31                  }
32              }
33              catch (ThreadAbortException ex)
34              {
35                  //输出终止线程时n的值
36                  if (ex.ExceptionState != null)
37                      Console.WriteLine(string.Format("Thread abort when the number is: {0}!", 
38                                                       ex.ExceptionState.ToString()));
39                 
40                  //取消终止,继续执行线程
41                  Thread.ResetAbort();
42                  Console.WriteLine("Thread ResetAbort!");
43              }
44  
45              //线程结束
46              Console.WriteLine("Thread Close!");
47          }

3.4 挂起线程

亿万先生: 25

为了等待别的后台线程实现后再结束主线程,就足以采取Thread.Sleep()方法。

运作结果如下

亿万先生: 26😉

亿万先生: 27

 1     public class Message  2     {  3         public void ShowMessage()  4         {  5             string message = string.Format("\nAsync threadId is:{0}",  6                                            Thread.CurrentThread.ManagedThreadId);  7             Console.WriteLine(message);  8             for (int n = 0; n < 10; n++)  9             { 10                 Thread.Sleep(300); 11                 Console.WriteLine("The number is:" + n.ToString()); 12             } 13         } 14     } 15  16     class Program 17     { 18         static void Main(string[] args) 19         {      20             Console.WriteLine("Main threadId is:"+ 21                               Thread.CurrentThread.ManagedThreadId); 22              23             Message message=new Message(); 24             Thread thread = new Thread(new ThreadStart(message.ShowMessage)); 25             thread.IsBackground = true; 26             thread.Start(); 27              28             Console.WriteLine("Do something ..........!"); 29             Console.WriteLine("Main thread working is complete!"); 30             Console.WriteLine("Main thread sleep!"); 31             Thread.Sleep(5000); 32         } 33     }

 

亿万先生: 28😉

 

运行结果如下,此时利用程序域将在主线程运维5秒后自动终止

回来目录

亿万先生: 29

肆 、CLTiggo线程池的劳力线程

 

4.1 关于CLR线程池

但系统不或者预见异步线程必要周转的年月,所以用经过Thread.Sleep(int)阻塞主线程并不是三个好的消除办法。有见及此,.NET专门为等候异步线程完结支付了另一个艺术thread.Join()。把地点例子中的最终一行Thread.Sleep(5000)修改为
thread.Join() 就能确认保证主线程在异步线程thread运维结束后才会终止。

利用ThreadStart与ParameterizedThreadStart建立新线程分外简单,但因此此格局创立的线程难于管理,若建立过多的线程反而会影响系统的性质。
有见及此,.NET引入CLLX570线程池那几个概念。CL本田UR-V线程池并不会在CL奥迪Q5开始化的时候立时创立线程,而是在应用程序要创设线程来施行职务时,线程池才初步化二个线程。线程的早先化与其它的线程一样。在成就职务之后,该线程不会活动销毁,而是以挂起的气象重返到线程池。直到应用程序再度向线程池发出请求时,线程池里挂起的线程就会重新激活执行职务。那样既节省了成立线程所导致的性质损耗,也足以让多个职务反复重用同一线程,从而在应用程序生存期内节约多量付出。

 

注意通过CL逍客线程池所创制的线程总是暗中同意为后台线程,优先级数为ThreadPriority.Normal。

3.5 Suspend 与 Resume (慎用)

 

Thread.Suspend()与 Thread.Resume()是在Framework1.0
就已经存在的老艺术了,它们分别能够挂起、恢复生机线程。但在Framework2.0中就曾经明显排斥那八个办法。这是因为一旦有个别线程占用了已有个别财富,再接纳Suspend()使线程短期居于挂起状态,当在此外线程调用那些能源的时候就会引起死锁!所以在未曾要求的情事下相应防止使用那多个点子。

4.2 工我线程与I/O线程

 

CL卡宴线程池分为工作者线程(workerThreads)与I/O线程 (completionPortThreads)
二种,工作者线程是首要用作管理CL冠道内部对象的周转,I/O(Input/Output)
线程顾名思义是用以与表面系统调换音讯,IO线程的细节将在下一节详细表明。

3.6 终止线程

因此ThreadPool.Get马克斯(out int workerThreads,out int
completionPortThreads )和 ThreadPool.Set马克斯( int workerThreads, int
completionPortThreads)多个情势能够分别读取和安装CLTiguan线程池安徽中华工程集团作者线程与I/O线程的最大线程数。在Framework2.0中最大线程暗中认可为25*CPU数,在Framewok3.0、4.0中最大线程数默许为250*CPU数,在近年
I3,I5,I7 CPU出现后,线程池的最大值一般默许为一千、三千。
若想测试线程池中有稍许的线程正在投入使用,能够经过ThreadPool.GetAvailableThreads( out
int workerThreads,out int completionPortThreads ) 方法。

若想终止正在运营的线程,能够行使Abort()方法。在动用Abort()的时候,将引发1个出奇至极ThreadAbortException 。 若想在线程终止前恢复生机线程的实施,能够在捕获十分后
,在catch(ThreadAbortException ex){…}
中调用Thread.ResetAbort()打消终止。
而使用Thread.Join()能够确定保障应用程序域等待异步线程截至后才告一段落运维。

动用CLLAND线程池的劳重力线程一般有二种方法,一是平素通过
ThreadPool.QueueUserWorkItem() 方法,二是透过信托,下边将顺序细说。

亿万先生: 30😉

 

 1          static void Main(string[] args)
 2          {
 3              Console.WriteLine("Main threadId is:" +
 4                                Thread.CurrentThread.ManagedThreadId);
 5  
 6              Thread thread = new Thread(new ThreadStart(AsyncThread));
 7              thread.IsBackground = true;
 8              thread.Start();
 9              thread.Join();
10  
11          }     
12          
13          //以异步方式调用
14          static void AsyncThread()
15          {
16              try
17              {
18                  string message = string.Format("\nAsync threadId is:{0}",
19                     Thread.CurrentThread.ManagedThreadId);
20                  Console.WriteLine(message);
21  
22                  for (int n = 0; n < 10; n++)
23                  {
24                      //当n等于4时,终止线程
25                      if (n >= 4)
26                      {
27                          Thread.CurrentThread.Abort(n);
28                      }
29                      Thread.Sleep(300);
30                      Console.WriteLine("The number is:" + n.ToString());
31                  }
32              }
33              catch (ThreadAbortException ex)
34              {
35                  //输出终止线程时n的值
36                  if (ex.ExceptionState != null)
37                      Console.WriteLine(string.Format("Thread abort when the number is: {0}!", 
38                                                       ex.ExceptionState.ToString()));
39                 
40                  //取消终止,继续执行线程
41                  Thread.ResetAbort();
42                  Console.WriteLine("Thread ResetAbort!");
43              }
44  
45              //线程结束
46              Console.WriteLine("Thread Close!");
47          }

4.3 通过QueueUserWorkItem运行工作者线程

亿万先生: 31😉

ThreadPool线程池中涵盖有多少个静态方法能够一贯开发银行工作者线程:
一为 ThreadPool.QueueUserWorkItem(WaitCallback)
二为 ThreadPool.QueueUserWorkItem(WaitCallback,Object) 

运维结果如下

先把WaitCallback委托指向1个分包Object参数的无重临值方法,再使用
ThreadPool.QueueUserWorkItem(WaitCallback)
就能够异步运转此格局,此时异步方法的参数被视为null 。

亿万先生: 32

亿万先生: 33

 

 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             //把CLR线程池的最大值设置为1000
 6             ThreadPool.SetMaxThreads(1000, 1000);
 7             //显示主线程启动时线程池信息
 8             ThreadMessage("Start");
 9             //启动工作者线程
10             ThreadPool.QueueUserWorkItem(new WaitCallback(AsyncCallback));
11             Console.ReadKey();
12         }
13         
14         static void AsyncCallback(object state)
15         {
16             Thread.Sleep(200);
17             ThreadMessage("AsyncCallback");
18             Console.WriteLine("Async thread do work!");
19         }
20 
21         //显示线程现状
22         static void ThreadMessage(string data)
23         {
24             string message = string.Format("{0}\n  CurrentThreadId is {1}",
25                  data, Thread.CurrentThread.ManagedThreadId);
26             Console.WriteLine(message);
27         }
28     }

 

亿万先生: 34

回去目录

运作结果

四 、CL昂科威线程池的劳力线程

亿万先生: 35

4.1 关于CLR线程池

 

选用ThreadStart与ParameterizedThreadStart建立新线程非凡简单,但经过此办法创设的线程难于管理,若建立过多的线程反而会潜移默化系统的属性。
有见及此,.NET引入CLENCORE线程池这几个概念。CLR线程池并不会在CLTiggo初阶化的时候登时创建线程,而是在应用程序要创设线程来执行任务时,线程池才初始化三个线程。线程的伊始化与任何的线程一样。在成功职分之后,该线程不会活动销毁,而是以挂起的动静重临到线程池。直到应用程序再度向线程池发出请求时,线程池里挂起的线程就会另行激活执行职务。那样既节省了建立线程所造成的属性损耗,也足以让多个任务反复重用同一线程,从而在应用程序生存期内节约大批量成本。

选用 ThreadPool.QueueUserWorkItem(WaitCallback,Object)
方法能够把object对象作为参数字传送送到回调函数中。
下边例子中就是把一个string对象作为参数发送到回调函数当中。

注意经过CLCRUISER线程池所树立的线程总是私下认可为后台线程,优先级数为ThreadPriority.Normal。

亿万先生: 36

 

 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             //把线程池的最大值设置为1000
 6             ThreadPool.SetMaxThreads(1000, 1000);
 7           
 8             ThreadMessage("Start");
 9             ThreadPool.QueueUserWorkItem(new WaitCallback(AsyncCallback),"Hello Elva");
10             Console.ReadKey();
11         }
12 
13         static void AsyncCallback(object state)
14         {
15             Thread.Sleep(200);
16             ThreadMessage("AsyncCallback");
17 
18             string data = (string)state;
19             Console.WriteLine("Async thread do work!\n"+data);
20         }
21 
22         //显示线程现状
23         static void ThreadMessage(string data)
24         {
25             string message = string.Format("{0}\n  CurrentThreadId is {1}",
26                  data, Thread.CurrentThread.ManagedThreadId);
27             Console.WriteLine(message);
28         }
29     }

4.2 工小编线程与I/O线程

亿万先生: 37

CL君越线程池分为工小编线程(workerThreads)与I/O线程 (completionPortThreads)
三种,工小编线程是重点用作管理CLLAND内部对象的运作,I/O(Input/Output)
线程顾名思义是用于与外表系统交流音讯,IO线程的细节将在下一节详细表达。

运维结果

经过ThreadPool.GetMax(out int workerThreads,out int
completionPortThreads )和 ThreadPool.Set马克斯( int workerThreads, int
completionPortThreads)几个艺术能够独家读取和设置CL普拉多线程池云南中华工程公司小编线程与I/O线程的最大线程数。在Framework2.0中最大线程暗许为25*CPU数,在Framewok3.0、4.0中最大线程数暗中认可为250*CPU数,在最近I3,I5,I7 CPU出现后,线程池的最大值一般暗中同意为1000、三千。
若想测试线程池中有多少的线程正在投入使用,能够通过ThreadPool.GetAvailableThreads(
out int workerThreads,out int
completionPortThreads ) 方法。

亿万先生: 38

运用CL本田UR-V线程池的工小编线程一般有二种办法,一是一向通过
ThreadPool.QueueUserWorkItem() 方法,二是透过委托,上面将相继细说。

 

 

通过ThreadPool.QueueUserWorkItem运营工我线程就算是福利,但WaitCallback委托指向的必须是3个蕴涵Object参数的无再次来到值方法,那无疑是一种范围。若方法须求有再次回到值,或然隐含多个参数,那将多费周折。有见及此,.NET提供了另一种方式去建立工我线程,那正是寄托。

4.3 通过QueueUserWorkItem运行工我线程

 

ThreadPool线程池中含有有多少个静态方法能够一贯开发银行工笔者线程: 一为
ThreadPool.QueueUserWorkItem(WaitCallback) 二为
ThreadPool.QueueUserWorkItem(WaitCallback,Object) 

4.4  委托类       

先把WaitCallback委托指向四个饱含Object参数的无重临值方法,再选用ThreadPool.QueueUserWorkItem(WaitCallback)
就能够异步运维此格局,此时异步方法的参数被视为null 。

采纳CL福睿斯线程池中的工小编线程,最灵敏最常用的办法便是利用委托的异步方法,在此先不难介绍一下委托类。

亿万先生: 39😉

当定义委托后,.NET就会自动创造2个意味着该信托的类,上面能够用反射格局展现委托类的方法成员(对反射有趣味的意中人能够先参考一下“.NET基础篇——反射的神妙”)

 1     class Program  2     {  3         static void Main(string[] args)  4         {  5             //把CLR线程池的最大值设置为1000  6             ThreadPool.SetMaxThreads(1000, 1000);  7             //显示主线程启动时线程池信息  8             ThreadMessage("Start");  9             //启动工作者线程 10             ThreadPool.QueueUserWorkItem(new WaitCallback(AsyncCallback)); 11             Console.ReadKey(); 12         } 13          14         static void AsyncCallback(object state) 15         { 16             Thread.Sleep(200); 17             ThreadMessage("AsyncCallback"); 18             Console.WriteLine("Async thread do work!"); 19         } 20  21         //显示线程现状 22         static void ThreadMessage(string data) 23         { 24             string message = string.Format("{0}\n  CurrentThreadId is {1}", 25                  data, Thread.CurrentThread.ManagedThreadId); 26             Console.WriteLine(message); 27         } 28     }

亿万先生: 40

亿万先生: 41😉

 1     class Program
 2     {
 3         delegate void MyDelegate();
 4 
 5         static void Main(string[] args)
 6         {
 7             MyDelegate delegate1 = new MyDelegate(AsyncThread);
 8             //显示委托类的几个方法成员     
 9             var methods=delegate1.GetType().GetMethods();
10             if (methods != null)
11                 foreach (MethodInfo info in methods)
12                     Console.WriteLine(info.Name);
13             Console.ReadKey();
14          }
15      }

运行结果

亿万先生: 42

亿万先生: 43

委托类包含以下多少个重点方式

 

亿万先生: 44

采纳 ThreadPool.QueueUserWorkItem(WaitCallback,Object)
方法可以把object对象作为参数字传送送到回调函数中。
上边例子中正是把三个string对象作为参数发送到回调函数个中。

亿万先生: 45

亿万先生: 46😉

1     public class MyDelegate:MulticastDelegate
2     {
3         public MyDelegate(object target, int methodPtr);
4         //调用委托方法
5         public virtual void Invoke();
6         //异步委托
7         public virtual IAsyncResult BeginInvoke(AsyncCallback callback,object state);
8         public virtual void EndInvoke(IAsyncResult result);
9     }
 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             //把线程池的最大值设置为1000
 6             ThreadPool.SetMaxThreads(1000, 1000);
 7           
 8             ThreadMessage("Start");
 9             ThreadPool.QueueUserWorkItem(new WaitCallback(AsyncCallback),"Hello Elva");
10             Console.ReadKey();
11         }
12 
13         static void AsyncCallback(object state)
14         {
15             Thread.Sleep(200);
16             ThreadMessage("AsyncCallback");
17 
18             string data = (string)state;
19             Console.WriteLine("Async thread do work!\n"+data);
20         }
21 
22         //显示线程现状
23         static void ThreadMessage(string data)
24         {
25             string message = string.Format("{0}\n  CurrentThreadId is {1}",
26                  data, Thread.CurrentThread.ManagedThreadId);
27             Console.WriteLine(message);
28         }
29     }

亿万先生: 47

亿万先生: 48😉

当调用Invoke()方法时,对应此委托的兼具办法都会被执行。而BeginInvoke与EndInvoke则协理委托方法的异步调用,由BeginInvoke运行的线程都属于CLLacrosse线程池中的工我线程,在底下将详细表达。

运维结果

 

亿万先生: 49

4.5  利用BeginInvoke与EndInvoke完毕异步委托方法

 

第第②建工公司立三个寄托对象,通过IAsyncResult BeginInvoke(string
name,AsyncCallback callback,object state) 异步调用委托方法,BeginInvoke
方法除末了的四个参数外,其余参数都以与艺术参数相对应的。通过 BeginInvoke
方法将赶回3个贯彻了 System.IAsyncResult
接口的指标,之后就足以选取EndInvoke(IAsyncResult )
方法就能够终结异步操作,获取委托的运转结果。

因此ThreadPool.QueueUserWorkItem运行工小编线程固然是造福,但WaitCallback委托指向的总得是三个涵盖Object参数的无再次回到值方法,那确实是一种限制。若方法需求有重回值,恐怕隐含四个参数,这将多费周折。有见及此,.NET提供了另一种办法去建立工笔者线程,那就是委托。

亿万先生: 50

 

 1     class Program
 2     {
 3         delegate string MyDelegate(string name);
 4 
 5         static void Main(string[] args)
 6         {
 7             ThreadMessage("Main Thread");
 8             
 9             //建立委托
10             MyDelegate myDelegate = new MyDelegate(Hello);
11             //异步调用委托,获取计算结果
12             IAsyncResult result=myDelegate.BeginInvoke("Leslie", null, null);
13             //完成主线程其他工作
14             ............. 
15             //等待异步方法完成,调用EndInvoke(IAsyncResult)获取运行结果
16             string data=myDelegate.EndInvoke(result);
17             Console.WriteLine(data);
18             
19             Console.ReadKey();
20         }
21 
22         static string Hello(string name)
23         {
24             ThreadMessage("Async Thread");
25             Thread.Sleep(2000);            //虚拟异步工作
26             return "Hello " + name;
27         }
28 
29         //显示当前线程
30         static void ThreadMessage(string data)
31         {
32             string message = string.Format("{0}\n  ThreadId is:{1}",
33                    data,Thread.CurrentThread.ManagedThreadId);
34             Console.WriteLine(message);
35         }
36     }

4.4  委托类       

亿万先生: 51

动用CLSportage线程池中的工作者线程,最灵敏最常用的主意便是选拔委托的异步方法,在此先简单介绍一下委托类。

运转结果

当定义委托后,.NET就会自行创设三个代表该信托的类,上面能够用反射方式呈现委托类的办法成员(对反射有趣味的爱人可以先参考一下“.NET基础篇——反射的微妙”)

亿万先生: 52

亿万先生: 53😉

 

 1     class Program  2     {  3         delegate void MyDelegate();  4   5         static void Main(string[] args)  6         {  7             MyDelegate delegate1 = new MyDelegate(AsyncThread);  8             //显示委托类的几个方法成员       9             var methods=delegate1.GetType().GetMethods(); 10             if (methods != null) 11                 foreach (MethodInfo info in methods) 12                     Console.WriteLine(info.Name); 13             Console.ReadKey(); 14          } 15      }

4.6  善用IAsyncResult

亿万先生: 54😉

在上述例子中得以望见,假使在运用myDelegate.BeginInvoke后立即调用myDelegate.EndInvoke,那在异步线程未成功工作此前主线程将处于阻塞状态,等到异步线程结束获取总计结果后,主线程才能一而再做事,那明摆着不能够显示出二十四线程的优势。此时得以能够利用IAsyncResult
提升主线程的劳作性质,IAsyncResult有以下成员:

委托类包罗以下多少个非常重要措施

亿万先生: 55

亿万先生: 56

1 public interface IAsyncResult
2 {
3     object AsyncState {get;}            //获取用户定义的对象,它限定或包含关于异步操作的信息。
4     WailHandle AsyncWaitHandle {get;}   //获取用于等待异步操作完成的 WaitHandle。
5     bool CompletedSynchronously {get;}  //获取异步操作是否同步完成的指示。
6     bool IsCompleted {get;}             //获取异步操作是否已完成的指示。
7 }

亿万先生: 57😉

亿万先生: 58

1     public class MyDelegate:MulticastDelegate
2     {
3         public MyDelegate(object target, int methodPtr);
4         //调用委托方法
5         public virtual void Invoke();
6         //异步委托
7         public virtual IAsyncResult BeginInvoke(AsyncCallback callback,object state);
8         public virtual void EndInvoke(IAsyncResult result);
9     }

通过轮询格局,使用IsCompleted属性判断异步操作是或不是成功,那样在异步操作未形成前就能够让主线程执行此外的办事。

亿万先生: 59😉

亿万先生: 60

当调用Invoke()方法时,对应此委托的有所办法都会被执行。而BeginInvoke与EndInvoke则扶助委托方法的异步调用,由BeginInvoke运维的线程都属于CL奇骏线程池中的工笔者线程,在底下将详细表达。

 1     class Program
 2     {
 3         delegate string MyDelegate(string name);
 4 
 5         static void Main(string[] args)
 6         {
 7             ThreadMessage("Main Thread");
 8             
 9             //建立委托
10             MyDelegate myDelegate = new MyDelegate(Hello);
11             //异步调用委托,获取计算结果
12             IAsyncResult result=myDelegate.BeginInvoke("Leslie", null, null);
13             //在异步线程未完成前执行其他工作
14             while (!result.IsCompleted)
15             {
16                 Thread.Sleep(200);      //虚拟操作
17                 Console.WriteLine("Main thead do work!");
18             }
19             string data=myDelegate.EndInvoke(result);
20             Console.WriteLine(data);
21             
22             Console.ReadKey();
23         }
24 
25         static string Hello(string name)
26         {
27             ThreadMessage("Async Thread");
28             Thread.Sleep(2000);
29             return "Hello " + name;
30         }
31 
32         static void ThreadMessage(string data)
33         {
34             string message = string.Format("{0}\n  ThreadId is:{1}",
35                    data,Thread.CurrentThread.ManagedThreadId);
36             Console.WriteLine(message);
37         }
38     }

 

亿万先生: 61

4.5  利用BeginInvoke与EndInvoke实现异步委托方法

运作结果:

第第③建工公司立一个信托对象,通过IAsyncResult BeginInvoke(string
name,AsyncCallback callback,object state) 异步调用委托方法,BeginInvoke
方法除最终的七个参数外,别的参数都以与方法参数相呼应的。通过 BeginInvoke
方法将回到2个落到实处了 System.IAsyncResult
接口的对象,之后就能够使用EndInvoke(IAsyncResult )
方法就足以终结异步操作,获取委托的运作结果。

亿万先生: 62

亿万先生: 63😉

 

 1     class Program  2     {  3         delegate string MyDelegate(string name);  4   5         static void Main(string[] args)  6         {  7             ThreadMessage("Main Thread");  8               9             //建立委托 10             MyDelegate myDelegate = new MyDelegate(Hello); 11             //异步调用委托,获取计算结果 12             IAsyncResult result=myDelegate.BeginInvoke("Leslie", null, null); 13             //完成主线程其他工作 14             .............  15             //等待异步方法完成,调用EndInvoke(IAsyncResult)获取运行结果 16             string data=myDelegate.EndInvoke(result); 17             Console.WriteLine(data); 18              19             Console.ReadKey(); 20         } 21  22         static string Hello(string name) 23         { 24             ThreadMessage("Async Thread"); 25             Thread.Sleep(2000);            //虚拟异步工作 26             return "Hello " + name; 27         } 28  29         //显示当前线程 30         static void ThreadMessage(string data) 31         { 32             string message = string.Format("{0}\n  ThreadId is:{1}", 33                    data,Thread.CurrentThread.ManagedThreadId); 34             Console.WriteLine(message); 35         } 36     }

除此以外,也得以应用WailHandle完结同样的做事,WaitHandle里面富含有二个主意WaitOne(int
timeout),它能够看清委托是还是不是做到工作,在工作未到位前主线程能够继续其余干活。运营上边代码可获得与利用
IAsyncResult.IsCompleted 同样的结果,而且更简约方便 。

亿万先生: 64😉

亿万先生: 65

运营结果

 1 namespace Test
 2 {
 3     class Program
 4     {
 5         delegate string MyDelegate(string name);
 6 
 7         static void Main(string[] args)
 8         {
 9             ThreadMessage("Main Thread");
10             
11             //建立委托
12             MyDelegate myDelegate = new MyDelegate(Hello);
13  
14             //异步调用委托,获取计算结果
15             IAsyncResult result=myDelegate.BeginInvoke("Leslie", null, null);
16             
17             while (!result.AsyncWaitHandle.WaitOne(200))
18             {
19                 Console.WriteLine("Main thead do work!");
20             }
21             string data=myDelegate.EndInvoke(result);
22             Console.WriteLine(data);
23             
24             Console.ReadKey();
25         }
26 
27         static string Hello(string name)
28         {
29             ThreadMessage("Async Thread");
30             Thread.Sleep(2000);
31             return "Hello " + name;
32         }
33 
34         static void ThreadMessage(string data)
35         {
36             string message = string.Format("{0}\n  ThreadId is:{1}",
37                    data,Thread.CurrentThread.ManagedThreadId);
38             Console.WriteLine(message);
39         }
40     }

亿万先生: 66

亿万先生: 67

 

当要监视五个运营目的的时候,使用IAsyncResult.WaitHandle.WaitOne可就派不上用场了。
幸亏.NET为WaitHandle准备了其它多个静态方法:WaitAny(waitHandle[],
int)与WaitAll (waitHandle[] , int)。
内部WaitAll在守候全数waitHandle达成后再再次回到三个bool值。
而WaitAny是等待之中三个waitHandle完毕后就重临3个int,这几个int是意味已到位waitHandle在waitHandle[]中的数组索引。
上面就是使用WaitAll的例证,运转结果与应用 IAsyncResult.IsCompleted
相同。

4.6  善用IAsyncResult

亿万先生: 68

在上述例子中得以瞥见,假若在运用myDelegate.BeginInvoke后马上调用myDelegate.EndInvoke,那在异步线程未到位工作以前主线程将处于阻塞状态,等到异步线程甘休获取计算结果后,主线程才能继续做事,那明摆着力不从心体现出二十八线程的优势。此时能够能够利用IAsyncResult
进步主线程的干活性质,IAsyncResult有以下成员:

 1     class Program
 2     {
 3         delegate string MyDelegate(string name);
 4 
 5         static void Main(string[] args)
 6         {
 7             ThreadMessage("Main Thread");
 8             
 9             //建立委托
10             MyDelegate myDelegate = new MyDelegate(Hello);
11  
12             //异步调用委托,获取计算结果
13             IAsyncResult result=myDelegate.BeginInvoke("Leslie", null, null);
14 
15             //此处可加入多个检测对象
16             WaitHandle[] waitHandleList = new WaitHandle[] { result.AsyncWaitHandle,........ };
17             while (!WaitHandle.WaitAll(waitHandleList,200))
18             {
19                 Console.WriteLine("Main thead do work!");
20             }
21             string data=myDelegate.EndInvoke(result);
22             Console.WriteLine(data);
23             
24             Console.ReadKey();
25         }
26 
27         static string Hello(string name)
28         {
29             ThreadMessage("Async Thread");
30             Thread.Sleep(2000);
31             return "Hello " + name;
32         }
33 
34         static void ThreadMessage(string data)
35         {
36             string message = string.Format("{0}\n  ThreadId is:{1}",
37                    data,Thread.CurrentThread.ManagedThreadId);
38             Console.WriteLine(message);
39         }
40     }

亿万先生: 69😉

亿万先生: 70

1 public interface IAsyncResult
2 {
3     object AsyncState {get;}            //获取用户定义的对象,它限定或包含关于异步操作的信息。
4     WailHandle AsyncWaitHandle {get;}   //获取用于等待异步操作完成的 WaitHandle。
5     bool CompletedSynchronously {get;}  //获取异步操作是否同步完成的指示。
6     bool IsCompleted {get;}             //获取异步操作是否已完成的指示。
7 }

 

亿万先生: 71😉

4.7 回调函数

通过轮询格局,使用IsCompleted属性判断异步操作是或不是实现,那样在异步操作未形成前就足以让主线程执行其余的劳作。

利用轮询形式来检查和测试异步方法的情事格外劳顿,而且功效不高,有见及此,.NET为
IAsyncResult BeginInvoke(AsyncCallback ,
object)准备了三个回调函数。使用 AsyncCallback
就能够绑定贰个主意作为回调函数,回调函数必须是带参数 IAsyncResult
且无再次来到值的不二法门: void AsycnCallbackMethod(IAsyncResult result)
。在BeginInvoke方法成功后,系统就会调用AsyncCallback所绑定的回调函数,最终回调函数中调用
XXX EndInvoke(IAsyncResult result)
就能够了结异步方法,它的回来值类型与寄托的再次回到值一致。

亿万先生: 72😉

亿万先生: 73

 1     class Program  2     {  3         delegate string MyDelegate(string name);  4   5         static void Main(string[] args)  6         {  7             ThreadMessage("Main Thread");  8               9             //建立委托 10             MyDelegate myDelegate = new MyDelegate(Hello); 11             //异步调用委托,获取计算结果 12             IAsyncResult result=myDelegate.BeginInvoke("Leslie", null, null); 13             //在异步线程未完成前执行其他工作 14             while (!result.IsCompleted) 15             { 16                 Thread.Sleep(200);      //虚拟操作 17                 Console.WriteLine("Main thead do work!"); 18             } 19             string data=myDelegate.EndInvoke(result); 20             Console.WriteLine(data); 21              22             Console.ReadKey(); 23         } 24  25         static string Hello(string name) 26         { 27             ThreadMessage("Async Thread"); 28             Thread.Sleep(2000); 29             return "Hello " + name; 30         } 31  32         static void ThreadMessage(string data) 33         { 34             string message = string.Format("{0}\n  ThreadId is:{1}", 35                    data,Thread.CurrentThread.ManagedThreadId); 36             Console.WriteLine(message); 37         } 38     }
 1     class Program
 2     {
 3         delegate string MyDelegate(string name);
 4 
 5         static void Main(string[] args)
 6         {
 7             ThreadMessage("Main Thread");
 8 
 9             //建立委托
10             MyDelegate myDelegate = new MyDelegate(Hello);
11             //异步调用委托,获取计算结果
12             myDelegate.BeginInvoke("Leslie", new AsyncCallback(Completed), null);
13             //在启动异步线程后,主线程可以继续工作而不需要等待
14             for (int n = 0; n < 6; n++)
15                 Console.WriteLine("  Main thread do work!");
16             Console.WriteLine("");
17 
18             Console.ReadKey();
19         }
20 
21         static string Hello(string name)
22         {
23             ThreadMessage("Async Thread");
24             Thread.Sleep(2000);             \\模拟异步操作
25             return "\nHello " + name;
26         }
27 
28         static void Completed(IAsyncResult result)
29         {
30             ThreadMessage("Async Completed");
31 
32             //获取委托对象,调用EndInvoke方法获取运行结果
33             AsyncResult _result = (AsyncResult)result;
34             MyDelegate myDelegate = (MyDelegate)_result.AsyncDelegate;
35             string data = myDelegate.EndInvoke(_result);
36             Console.WriteLine(data);
37         }
38 
39         static void ThreadMessage(string data)
40         {
41             string message = string.Format("{0}\n  ThreadId is:{1}",
42                    data, Thread.CurrentThread.ManagedThreadId);
43             Console.WriteLine(message);
44         }
45     }

亿万先生: 74😉

亿万先生: 75

运转结果:

能够见见,主线在调用BeginInvoke方法能够继续执行别的命令,而无需再等待了,这活脱脱比使用轮询格局判断异步方法是不是完结更有优势。
在异步方法执行到位后将会调用AsyncCallback所绑定的回调函数,注意一点,回调函数依然是在异步线程中履行,那样就不会影响主线程的周转,那也选择回调函数最值得青昧的地点。
在回调函数中有一个既定的参数IAsyncResult,把IAsyncResult强制转换为AsyncResult后,就足以经过
AsyncResult.AsyncDelegate
获取原委托,再利用EndInvoke方法获得计算结果。
运维结果如下:

亿万先生: 76

亿万先生: 77

 

假使想为回调函数字传送送一些外部信息,就能够动用BeginInvoke(AsyncCallback,object)的末段1个参数object,它同意外部向回调函数输入任何类型的参数。只需求在回调函数中应用
AsyncResult.AsyncState 就足以获得object对象。

除此以外,也能够采纳WailHandle完毕同样的劳作,WaitHandle里面含有有2个格局WaitOne(int
timeout),它能够看清委托是不是完结工作,在工作未到位前主线程能够一连别的干活。运维下边代码可拿到与利用
IAsyncResult.IsCompleted 同样的结果,而且更简便方便 。

亿万先生: 78

亿万先生: 79😉

 1     class Program
 2     {
 3         public class Person
 4         {
 5             public string Name;
 6             public int Age;
 7         }
 8 
 9         delegate string MyDelegate(string name);
10 
11         static void Main(string[] args)
12         {
13             ThreadMessage("Main Thread");
14 
15             //建立委托
16             MyDelegate myDelegate = new MyDelegate(Hello);
17             
18             //建立Person对象
19             Person person = new Person();
20             person.Name = "Elva";
21             person.Age = 27;
22             
23             //异步调用委托,输入参数对象person, 获取计算结果
24             myDelegate.BeginInvoke("Leslie", new AsyncCallback(Completed), person);            
25           
26             //在启动异步线程后,主线程可以继续工作而不需要等待
27             for (int n = 0; n < 6; n++)
28                 Console.WriteLine("  Main thread do work!");
29             Console.WriteLine("");
30 
31             Console.ReadKey();
32         }
33 
34         static string Hello(string name)
35         {
36             ThreadMessage("Async Thread");
37             Thread.Sleep(2000);
38             return "\nHello " + name;
39         }
40 
41         static void Completed(IAsyncResult result)
42         {
43             ThreadMessage("Async Completed");
44 
45             //获取委托对象,调用EndInvoke方法获取运行结果
46             AsyncResult _result = (AsyncResult)result;
47             MyDelegate myDelegate = (MyDelegate)_result.AsyncDelegate;
48             string data = myDelegate.EndInvoke(_result);
49             //获取Person对象
50             Person person = (Person)result.AsyncState;
51             string message = person.Name + "'s age is " + person.Age.ToString();
52 
53             Console.WriteLine(data+"\n"+message);
54         }
55 
56         static void ThreadMessage(string data)
57         {
58             string message = string.Format("{0}\n  ThreadId is:{1}",
59                    data, Thread.CurrentThread.ManagedThreadId);
60             Console.WriteLine(message);
61         }
62     }
 1 namespace Test
 2 {
 3     class Program
 4     {
 5         delegate string MyDelegate(string name);
 6 
 7         static void Main(string[] args)
 8         {
 9             ThreadMessage("Main Thread");
10             
11             //建立委托
12             MyDelegate myDelegate = new MyDelegate(Hello);
13  
14             //异步调用委托,获取计算结果
15             IAsyncResult result=myDelegate.BeginInvoke("Leslie", null, null);
16             
17             while (!result.AsyncWaitHandle.WaitOne(200))
18             {
19                 Console.WriteLine("Main thead do work!");
20             }
21             string data=myDelegate.EndInvoke(result);
22             Console.WriteLine(data);
23             
24             Console.ReadKey();
25         }
26 
27         static string Hello(string name)
28         {
29             ThreadMessage("Async Thread");
30             Thread.Sleep(2000);
31             return "Hello " + name;
32         }
33 
34         static void ThreadMessage(string data)
35         {
36             string message = string.Format("{0}\n  ThreadId is:{1}",
37                    data,Thread.CurrentThread.ManagedThreadId);
38             Console.WriteLine(message);
39         }
40     }

亿万先生: 80

亿万先生: 81😉

运转结果:

当要监视七个运维目的的时候,使用IAsyncResult.WaitHandle.WaitOne可就派不上用场了。
幸亏.NET为WaitHandle准备了此外多个静态方法:WaitAny(waitHandle[]亿万先生:,,
int)与WaitAll (waitHandle[] , int)。
当中WaitAll在等候全数waitHandle完毕后再回到1个bool值。
而WaitAny是伺机之中一个waitHandle完结后就回到3个int,那一个int是意味着已到位waitHandle在waitHandle[]中的数组索引。
下边正是运用WaitAll的例子,运转结果与行使 IAsyncResult.IsCompleted
相同。

亿万先生: 82

亿万先生: 83😉

 

 1     class Program  2     {  3         delegate string MyDelegate(string name);  4   5         static void Main(string[] args)  6         {  7             ThreadMessage("Main Thread");  8               9             //建立委托 10             MyDelegate myDelegate = new MyDelegate(Hello); 11   12             //异步调用委托,获取计算结果 13             IAsyncResult result=myDelegate.BeginInvoke("Leslie", null, null); 14  15             //此处可加入多个检测对象 16             WaitHandle[] waitHandleList = new WaitHandle[] { result.AsyncWaitHandle,........ }; 17             while (!WaitHandle.WaitAll(waitHandleList,200)) 18             { 19                 Console.WriteLine("Main thead do work!"); 20             } 21             string data=myDelegate.EndInvoke(result); 22             Console.WriteLine(data); 23              24             Console.ReadKey(); 25         } 26  27         static string Hello(string name) 28         { 29             ThreadMessage("Async Thread"); 30             Thread.Sleep(2000); 31             return "Hello " + name; 32         } 33  34         static void ThreadMessage(string data) 35         { 36             string message = string.Format("{0}\n  ThreadId is:{1}", 37                    data,Thread.CurrentThread.ManagedThreadId); 38             Console.WriteLine(message); 39         } 40     }

转载于:http://www.cnblogs.com/leslies2/archive/2012/02/07/2310495.html
 

亿万先生: 84😉

 

4.7 回调函数

选取轮询情势来检查和测试异步方法的意况不行麻烦,而且功用不高,有见及此,.NET为
IAsyncResult BeginInvoke(AsyncCallback ,
object)准备了一个回调函数。使用 AsyncCallback
就足以绑定3个方式作为回调函数,回调函数必须是带参数 IAsyncResult
且无再次回到值的章程: void AsycnCallbackMethod(IAsyncResult result)
。在BeginInvoke方法成功后,系统就会调用AsyncCallback所绑定的回调函数,最终回调函数中调用
XXX EndInvoke(IAsyncResult result)
就足以终结异步方法,它的回来值类型与寄托的重回值一致。

亿万先生: 85😉

 1     class Program
 2     {
 3         delegate string MyDelegate(string name);
 4 
 5         static void Main(string[] args)
 6         {
 7             ThreadMessage("Main Thread");
 8 
 9             //建立委托
10             MyDelegate myDelegate = new MyDelegate(Hello);
11             //异步调用委托,获取计算结果
12             myDelegate.BeginInvoke("Leslie", new AsyncCallback(Completed), null);
13             //在启动异步线程后,主线程可以继续工作而不需要等待
14             for (int n = 0; n < 6; n++)
15                 Console.WriteLine("  Main thread do work!");
16             Console.WriteLine("");
17 
18             Console.ReadKey();
19         }
20 
21         static string Hello(string name)
22         {
23             ThreadMessage("Async Thread");
24             Thread.Sleep(2000);             \\模拟异步操作
25             return "\nHello " + name;
26         }
27 
28         static void Completed(IAsyncResult result)
29         {
30             ThreadMessage("Async Completed");
31 
32             //获取委托对象,调用EndInvoke方法获取运行结果
33             AsyncResult _result = (AsyncResult)result;
34             MyDelegate myDelegate = (MyDelegate)_result.AsyncDelegate;
35             string data = myDelegate.EndInvoke(_result);
36             Console.WriteLine(data);
37         }
38 
39         static void ThreadMessage(string data)
40         {
41             string message = string.Format("{0}\n  ThreadId is:{1}",
42                    data, Thread.CurrentThread.ManagedThreadId);
43             Console.WriteLine(message);
44         }
45     }

亿万先生: 86😉

能够看出,主线在调用BeginInvoke方法能够继续执行其余命令,而无需再等待了,那无疑比使用轮询格局判断异步方法是还是不是做到更有优势。
在异步方法执行到位后将会调用AsyncCallback所绑定的回调函数,注意一点,回调函数依旧是在异步线程中履行,那样就不会潜移默化主线程的运营,那也应用回调函数最值得青昧的地方。
在回调函数中有1个既定的参数IAsyncResult,把IAsyncResult强制转换为AsyncResult后,就可以通过
AsyncResult.AsyncDelegate 获取原委托,再采纳EndInvoke方法获得总括结果。
运转结果如下:

亿万先生: 87

只要想为回调函数字传送送一些外部音讯,就足以采取BeginInvoke(AsyncCallback,object)的尾声叁个参数object,它同意外部向回调函数输入任何项指标参数。只必要在回调函数中动用
AsyncResult.AsyncState 就足以拿走object对象。

亿万先生: 88😉

 1     class Program  2     {  3         public class Person  4         {  5             public string Name;  6             public int Age;  7         }  8   9         delegate string MyDelegate(string name); 10  11         static void Main(string[] args) 12         { 13             ThreadMessage("Main Thread"); 14  15             //建立委托 16             MyDelegate myDelegate = new MyDelegate(Hello); 17              18             //建立Person对象 19             Person person = new Person(); 20             person.Name = "Elva"; 21             person.Age = 27; 22              23             //异步调用委托,输入参数对象person, 获取计算结果 24             myDelegate.BeginInvoke("Leslie", new AsyncCallback(Completed), person);             25            26             //在启动异步线程后,主线程可以继续工作而不需要等待 27             for (int n = 0; n < 6; n++) 28                 Console.WriteLine("  Main thread do work!"); 29             Console.WriteLine(""); 30  31             Console.ReadKey(); 32         } 33  34         static string Hello(string name) 35         { 36             ThreadMessage("Async Thread"); 37             Thread.Sleep(2000); 38             return "\nHello " + name; 39         } 40  41         static void Completed(IAsyncResult result) 42         { 43             ThreadMessage("Async Completed"); 44  45             //获取委托对象,调用EndInvoke方法获取运行结果 46             AsyncResult _result = (AsyncResult)result; 47             MyDelegate myDelegate = (MyDelegate)_result.AsyncDelegate; 48             string data = myDelegate.EndInvoke(_result); 49             //获取Person对象 50             Person person = (Person)result.AsyncState; 51             string message = person.Name + "'s age is " + person.Age.ToString(); 52  53             Console.WriteLine(data+"\n"+message); 54         } 55  56         static void ThreadMessage(string data) 57         { 58             string message = string.Format("{0}\n  ThreadId is:{1}", 59                    data, Thread.CurrentThread.ManagedThreadId); 60             Console.WriteLine(message); 61         } 62     }

亿万先生: 89😉

运转结果:

亿万先生: 90

 

关于I/O线程、SqlCommand二十八线程查询、PLINQ、定时器与锁的剧情将在C#归咎揭秘——细说八线程(下)中详细介绍。
对 .NET 开发有趣味的爱人欢迎插足QQ群:230564952
共同商量 !

回到目录

C#汇总揭秘

因而改动注册表建立Windows自定义协议
Entity Framework
并发处理详解
前述进度、应用程序域与上下文

细说二十三二十四线程(上)

细说二十多线程(下) 细说事务深深剖析委托与事件

 

小编:风尘浪子 http://www.cnblogs.com/leslies2/archive/2012/02/07/2310495.html

原创小说,转发时请证明我及出处

 

 

 

分类:
C#归纳揭秘

相关文章

网站地图xml地图