【美高梅开户网址】线程池的使用,使用线程池管理线程

CL昂科拉线程池并不会在CLCRUISER初叶化时马上成立线程,而是在应用程序要成立线程来运维任务时,线程池才开端化三个线程。
线程池发轫化时是从未线程的,线程池里的线程的初始化与此外线程一样,可是在成功任务之后,该线程不会自动销毁,而是以挂起的景观重临到线程池。直到应用程序再度向线程池发出请求时,线程池里挂起的线程就会另行激活执行职责。
诸如此类既节约了成立线程所导致的质量损耗,也足以让五个义务反复重用同一线程,从而在应用程序生存期内节约大批量支付。

今天我们来谈谈线程池:

  缘何使用线程池?  

异步编制程序:使用线程池管理线程,异步线程

异步编制程序:使用线程池管理线程

美高梅开户网址 1

 从此图中大家会意识 .NET 与C#
的各样版本发表都以有多个“核心”。即:C#一.0托管代码→C#2.0泛型→C#3.0LINQ→C#4.0动态语言→C#伍.0异步编制程序。以后自笔者为流行版本的“异步编制程序”核心写种类分享,期待你的查看及点评。

 

当今的应用程序越来越复杂,大家日常要求使用《异步编制程序:线程概述及利用》中关系的多线程技术来增加应用程序的响应速度。那时咱们往往的创制和销毁线程来让应用程序飞速响应操作,那频仍的始建和销毁无疑会降低应用程序质量,我们得以引入缓存机制化解那几个题材,此缓存机制亟待消除如:缓存的轻重难点、排队执行职分、调度空闲线程、按需创制新线程及销毁多余空闲线程……近期微软已经为我们提供了现成的缓存机制:线程池

        
线程池原自于对象池,在事无巨细解释明线程池前让大家先来领会下何为对象池。

流程图:

 美高梅开户网址 2

 

         对于对象池的清理常常设计二种格局:

一)         手动清理,即积极调用清理的措施。

二)         自动清理,即经过System.Threading.提姆er来完结定时清理。

 

根本落成代码:

 

  美高梅开户网址 3public
sealed class ObjectPool<T> where T : ICacheObjectProxy<T> {
// 最大容积 private Int32 m_maxPoolCount = 30; // 最小容积 private
Int3二 m_minPoolCount = 伍; // 已存容积 private Int3二 m_currentCount; //
空闲+被用 对象列表 private Hashtable m_listObjects; // 最大空闲时间
private int maxIdleTime = 120; // 定时清理对象池指标 private Timer timer
= null; /// <summary> /// 创设对象池 /// </summary> ///
<param name=”maxPoolCount”>最小容积</param> /// <param
name=”minPoolCount”>最大体量</param> /// <param
name=”create_params”>待创立的实际目的的参数</param> public
ObjectPool(Int32 maxPoolCount, Int3二 minPoolCount, Object[]
create_params){ } /// <summary> /// 获取2个目的实例 ///
</summary> ///
<returns>重临内部实际指标,若再次回到null则线程池已满</returns>
public T GetOne(){ } /// <summary> /// 释放该目标池 ///
</summary> public void Dispose(){ } /// <summary> ///
将目的池中钦点的靶子重置并设置为空闲状态 /// </summary> public
void ReturnOne(T obj){ } /// <summary> /// 手动清理对象池 ///
</summary> public void 马努alReleaseObject(){ } ///
<summary> /// 自动清理对象池(对超过 最小体积 的悠闲对象举办自由)
/// </summary> private void AutoReleaseObject(Object obj){ } }
完成的首要代码

 

因而对“对象池”的一个大致认识能帮大家更快通晓线程池。

 

线程池ThreadPool类详解

ThreadPool静态类,为应用程序提供3个由系统一管理理的帮忙线程池,从而使你能够集中精力于应用程序职务而不是线程管理。每一个进度都有一个线程池,二个Process中只好有三个实例,它在逐一应用程序域(AppDomain)是共享的。

在个中,线程池将团结的线程划分工小编线程(协助线程)和I/O线程。前者用于实践平日的操作,后者专用于异步IO,比如文件和网络请求,注意,分类并不表明三种线程自身有差别,内部照旧是均等的。

美高梅开户网址 4public
static class ThreadPool { //
将操作系统句柄绑定到System.Threading.ThreadPool。 public static bool
BindHandle(SafeHandle osHandle); //
检索由ThreadPool.Get马克斯Threads(Int32,Int3二)方法重临的最大线程池线程数和脚下活动线程数之间的差值。
public static void GetAvailableThreads(out int workerThreads , out int
completionPortThreads); //
设置和摸索能够同时处于活动状态的线程池请求的数据。 //
全部大于此数量的伏乞将保持排队状态,直到线程池线程变为可用。 public
static bool Set马克斯Threads(int workerThreads, int completionPortThreads);
public static void GetMaxThreads(out int workerThreads, out int
completionPortThreads); //
设置和检索线程池在新请求预测中爱护的空闲线程数。 public static bool
SetMinThreads(int workerThreads, int completionPortThreads); public
static void GetMinThreads(out int workerThreads, out int
completionPortThreads); //
将艺术排入队列以便执行,并点名包蕴该方法所用数据的靶子。此办法在无线程池线程变得可用时实施。
public static bool QueueUserWorkItem(WaitCallback callBack, object
state); // 将重叠的 I/O 操作排队以便执行。若是成功地将此操作排队到 I/O
完结端口,则为 true;不然为 false。 //
参数overlapped:要排队的System.Threading.NativeOverlapped结构。 public
static bool UnsafeQueueNativeOverlapped(NativeOverlapped* overlapped);
// 将钦命的嘱托排队到线程池,但不会将调用堆栈传播到劳引力线程。 public
static bool UnsafeQueueUserWorkItem(WaitCallback callBack, object
state); // 注册3个等待Threading.WaitHandle的委托,并点名3个 31人有号子整数来代表超时值(以皮秒为单位)。 // executeOnlyOnce倘若为
true,表示在调用了委托后,线程将不再在waitObject参数上等待; // 如果为
false,表示每一趟完结等待操作后都重置计时器,直到撤废等待。 public static
RegisteredWaitHandle RegisterWaitForSingleObject( WaitHandle waitObject
, WaitOrTimerCallback callBack, object state, Int
millisecondsTimeOutInterval, bool executeOnlyOnce); public static
RegisteredWaitHandle UnsafeRegisterWaitForSingleObject( WaitHandle
waitObject , WaitOrTimerCallback callBack , object state , int
millisecondsTimeOutInterval , bool executeOnlyOnce); …… } ThreadPool

一)         使用Get马克斯Threads()和SetMaxThreads()获取和设置最大线程数

可排队到线程池的操作数仅受内部存款和储蓄器的限定;而线程池限制进度中得以同时处于活动状态的线程数(私下认可处境下,限制每个CPU 能够利用 2五 个工小编线程和 一,000 个 I/O 线程(依据机器CPU个数和.net
framework版本的两样,这一个多少恐怕会有生成)),全体大于此数据的伏乞将保持排队情形,直到线程池线程变为可用。

不提出更改线程池中的最大线程数:

a)        
将线程池大小设置得太大,恐怕会造成更频仍的施行上下文切换及深化能源的争用情况。

b)        
其实FileStream的异步读写,异步发送接受Web请求,System.Threading.提姆er定时器,甚至动用delegate的beginInvoke都会暗中同意调用
ThreadPool,也便是说不仅你的代码只怕采纳到线程池,框架之中也说不定使用到。

c)        
二个选用程序池是两个单独的进度,拥有1个线程池,应用程序池中能够有八个WebApplication,各样运营在贰个独立的AppDomain中,这一个WebApplication公用二个线程池。

 

二)         使用GetMinThreads()和SetMinThreads()获取和设置最小空闲线程数

为制止向线程分配不供给的堆栈空间,线程池依照一定的流年距离成立新的闲暇线程(该距离为半秒)。所以只要最小空闲线程数设置的过小,在长期内执行大气职务会因为创立新空闲线程的嵌入延迟导致质量瓶颈。最小空闲线程数暗中认可值等于机械上的CPU核数,并且不提出改变最小空闲线程数。

在运维线程池时,线程池具有3个放到延迟,用于启用最小空闲线程数,以增加应用程序的吞吐量。

在线程池运维中,对于推行完职责的线程池线程,不会即时销毁,而是重回到线程池,线程池会维护最小的空闲线程数(即便应用程序全体线程都以悠闲状态),以便队列任务能够马上运维。超越此最小数指标悠闲线程1段时间没事做后会自身醒来终止本身,以节省系统财富。

三)         静态方法GetAvailableThreads()

【美高梅开户网址】线程池的使用,使用线程池管理线程。经过静态方法GetAvailableThreads()再次来到的线程池线程的最大数目和当前运动数量之间的差值,即获取线程池中当前可用的线程数目

4)         五个参数

艺术Get马克斯Threads()、Set马克斯Threads()、GetMinThreads()、SetMinThreads()、GetAvailableThreads()钧包涵四个参数。参数workerThreads指工笔者线程;参数completionPortThreads指异步
I/O 线程。

通过调用 ThreadPool.QueueUserWorkItem 并传递 WaitCallback
委托来使用线程池。也得以透过动用 ThreadPool.RegisterWaitForSingleObject
并传递 WaitHandle(在向其发出时限信号或过期时,它将引发对由
WaitOrTimerCallback
委托包装的不二秘籍的调用)来将与等待操作相关的干活项排队到线程池中。若要撤除等待操作(即不再执行WaitOrTimerCallback委托),可调用RegisterWaitForSingleObject()方法再次来到的RegisteredWaitHandle的
Unregister 方法。

一经您领略调用方的仓库与在排队职责履行期间履行的享有平安全检查查不相干,则还足以行使不安全的法子
ThreadPool.UnsafeQueueUserWorkItem 和
ThreadPool.UnsafeRegisterWaitForSingleObject。QueueUserWorkItem 和
RegisterWaitForSingleObject
都会捕获调用方的库房,此堆栈将在线程池线程发轫推行职务时合并到线程池线程的堆栈中。如若急需进行安全检查,则必须检查整个堆栈,但它还拥有自然的属性开支。使用“不安全的”方法调用并不会提供相对的安全,但它会提供更好的习性。

让1个线程不分明地等候八个基本对象进入可用状态,那对线程的内部存款和储蓄器财富来说是1种浪费。ThreadPool.RegisterWaitForSingleObject()为大家提供了1种艺术:在2个水源对象变得可用的时候调用2个格局。

应用需注意:

一)         WaitOrTimerCallback委托参数,该信托接受二个名叫timeOut的Boolean参数。倘使 WaitHandle 在钦赐时间内尚未接过频域信号(即,超时),则为true,不然为 false。回调方法能够依据timeOut的值来针对地选取措施。

二)         名叫executeOnlyOnce的Boolean参数。传true则象征线程池线程只举行回调方法2遍;若传false则代表内核查象每一回接到功率信号,线程池线程都会履行回调方法。等待三个AutoReset伊芙nt对象时,那些功效特别有用。

叁)         RegisterWaitForSingleObject()方法再次来到1个RegisteredWaitHandle对象的引用。这一个指标标识了线程池正在它下边等待的基业对象。大家得以调用它的Unregister(WaitHandle
waitObject)方法打消由RegisterWaitForSingleObject()注册的等候操作(即WaitOrTimerCallback委托不再履行)。Unregister(WaitHandle
waitObject)的WaitHandle参数表示成功撤废注册的等候操作后线程池会向此目的发出能量信号(set()),若不想接受此公告能够传递null。

         示例:

美高梅开户网址 5private
static void Example_RegisterWaitForSingleObject() { //
加endWaitHandle的来由:若是推行过快退出办法会导致有个别东西被放出,造成排队的职分不可能执行,原因还在商量AutoReset伊芙nt endWaitHandle = new AutoReset伊夫nt(false); AutoReset伊芙nt
notificWaitHandle = new AutoReset伊夫nt(false); AutoReset伊夫nt waitHandle
= new AutoReset伊夫nt(false); RegisteredWaitHandle registeredWaitHandle =
ThreadPool.RegisterWaitForSingleObject( waitHandle, (Object state, bool
timedOut) => { if (timedOut)
Console.WriteLine(“RegisterWaitForSingleObject因超时而执行”); else
Console.WriteLine(“RegisterWaitForSingleObject收到WaitHandle数字信号”); },
null, 提姆eSpan.FromSeconds(贰), true ); //
打消等待操作(即不再实施WaitOr提姆erCallback委托)
registeredWaitHandle.Unregister(notificWaitHandle); // 通告ThreadPool.RegisterWaitForSingleObject( notificWaitHandle, (Object
state, bool timedOut) => { if (timedOut)
Console.WriteLine(“第一个RegisterWaitForSingleObject未有调用Unregister()”);
else
Console.WriteLine(“第两个RegisterWaitForSingleObject调用了Unregister()”);
endWaitHandle.Set(); }, null, TimeSpan.FromSeconds(4), true );
endWaitHandle.WaitOne(); } 示例

施行上下文

        
上一小节中聊起:线程池最大线程数设置过大可能会导致Windows频仍执行上下文切换,降低程序质量。对于大多数园友不会满意那样的对答,小编和您壹样也高兴“知其然,再知其所以然”。

.NET中上下文太多,作者最后得出的定论是:上下文切换中的上下文专指“执行上下文”。

履行上下文包含:安全上下文、同步上下文(System.Threading.SynchronizationContext)、逻辑调用上下文(System.Runtime.Messaging.CallContext)。即:安全设置(压缩栈、Thread的Principal属性和Windows身份)、宿主设置(System.Threading.HostExcecutingContextManager)以及逻辑调用上下文数据(System.Runtime.Messaging.CallContext的LogicalSetData()和LogicalGetData()方法)。

当一个“时间片”甘休时,假若Windows决定再度调度同3个线程,那么Windows不会履行上下文切换。假诺Windows调度了3个不一致的线程,那时Windows执行线程上下文切换。

        
当Windows上下文切换来另二个线程时,CPU将推行贰个不如的线程,而以前线程的代码和数码还在CPU的高速缓存中,(高速缓存使CPU不必平日访问RAM,RAM的快慢比CPU高速缓存慢得多),当Windows上下文切换来三个新线程时,那些新线程极有十分的大概率要进行不一样的代码并走访分化的数目,这几个代码和数目不在CPU的高速缓存中。因而,CPU必须访问RAM来填充它的高速缓存,以恢复生机相当的慢实汇兑况。不过,在其“时间片”执行完后,壹回新的线程上下文切换又发生了。

上下文切换所发出的付出不会换到任何内部存款和储蓄器和性质上的收入。执行上下文所需的时间取决于CPU框架结构和速度(即“时间片”的分配)。而填充CPU缓存所需的时日取决于系统运维的应用程序、CPU、缓存的轻重缓急以及任何各样因素。所以,不能为每二次线程上下文切换的光阴支付给出3个规定的值,甚至胸中无数提交贰个测度的值。唯1分明的是,假诺要营造高品质的应用程序和零部件,就应有尽大概制止线程上下文切换。

除却,执行垃圾回收时,CLHaval必须挂起(暂停)全部线程,遍历它们的栈来查找根以便对堆中的对象开始展览标记,再度遍历它们的栈(有的对象在缩减期间产生了移动,所以要翻新它们的根),再回复全体线程。所以,收缩线程的数额也会理解进步垃圾回收器的质量。每回使用1个调节和测试器并蒙受2个断点,Windows都会挂起正在调节和测试的应用程序中的全数线程,并在单步执行或运转应用程序时回涨全数线程。因而,你用的线程更加多,调节和测试体验也就越差。

Windows实际记录了每一个线程被上下文切换成的次数。能够行使像Microsoft
Spy++那样的工具查看那些数额。那一个工具是Visual
Studio附带的3个小工具(vs按安装路径\Visual Studio
2012\Common7\Tools),如图

美高梅开户网址 6

在《异步编制程序:线程概述及应用》中自己提到了Thread的八个上下文,即:

一)         CurrentContext       
获取线程正在内部实施的日前上下文。首要用以线程内部存储数据。

二)         ExecutionContext   
获取二个System.Threading.ExecutionContext对象,该目的涵盖关于当前线程的种种上下文的新闻。主要用以线程间数据共享。

中间赢获得的System.Threading.ExecutionContext正是本小节要说的“执行上下文”。

美高梅开户网址 7public
sealed class ExecutionContext : IDisposable, ISerializable { public void
Dispose(); public void GetObjectData(SerializationInfo info,
StreamingContext context); //
此办法对于将履行上下文从三个线程传播到另多个线程1贰分有效。 public
ExecutionContext CreateCopy(); // 从此时此刻线程捕获执行上下文的一个副本。
public static ExecutionContext Capture(); //
在近来线程上的钦定执行上下文中运作有个别方法。 public static void
Run(ExecutionContext executionContext, ContextCallback callback, object
state); // 撤废执行上下文在异步线程之间的流淌。 public static
AsyncFlowControl SuppressFlow(); public static bool IsFlowSuppressed();
// RestoreFlow 撤销此前的 SuppressFlow 方法调用的熏陶。 // 此方法由
SuppressFlow 方法再次回到的 AsyncFlowControl 结构的 Undo 方法调用。 //
应使用 Undo 方法(而不是 RestoreFlow 方法)苏醒执行上下文的流淌。 public
static void RestoreFlow(); } View
Code

ExecutionContext
类提供的机能让用户代码可以在用户定义的异步点之间捕获和传导此上下文。公共语言运转时(CLPRADO)确认保障在托管进度内运维时定义的异步点之间同样地传输
ExecutionContext。

每当多个线程(发轫线程)使用另二个线程(协助线程)执行职分时,CL酷威会将前者的实施上下文流向(复制到)协助线程(注意那几个活动流向是单方向的)。这就保障了扶助线程执行的别的操作使用的是壹致的金昌设置和宿主设置。还有限协助了伊始线程的逻辑调用上下文能够在帮衬线程中选拔。

但执行上下文的复制会招致一定的性情影响。因为执行上下文中包罗大批量新闻,而采访全部这个音讯,再把它们复制到协助线程,要费用成千成万小时。假使援助线程又选拔了越多地帮忙线程,还必须成立和早先化越多的推行上下文数据结构。

从而,为了提高应用程序品质,我们能够阻挡实施上下文的流淌。当然那唯有在赞助线程不供给恐怕不访问上下文消息的时候才能拓展拦截。

上面给出3个示范为了演示:

一)         在线程间共享逻辑调用上下文数据(CallContext)。

2)         为了进步品质,阻止\光复执行上下文的流动。

三)         在近期线程上的内定执行上下文中运作有个别方法。

美高梅开户网址 8private
static void Example_ExecutionContext() {
CallContext.LogicalSetData(“Name”, “小红”);
Console.WriteLine(“主线程中Name为:{0}”,
CallContext.LogicalGetData(“Name”)); // 一)
在线程间共享逻辑调用上下文数据(CallContext)。
Console.WriteLine(“一)在线程间共享逻辑调用上下文数据(CallContext)。”);
ThreadPool.QueueUserWorkItem((Object obj) =>
Console.WriteLine(“ThreadPool线程中Name为:\”{0}\””,
CallContext.LogicalGetData(“Name”))); Thread.Sleep(500);
Console.WriteLine(); // 二) 为了提高质量,撤消\过来执行上下文的流动。
ThreadPool.UnsafeQueueUserWorkItem((Object obj) =>
Console.WriteLine(“ThreadPool线程使用Unsafe异步执行措施来撤除执行上下文的流动。Name为:\”{0}\美高梅开户网址 ,””
, CallContext.LogicalGetData(“Name”)), null);
Console.WriteLine(“2)为了进步品质,撤废/复苏执行上下文的流淌。”);
AsyncFlowControl flowControl = ExecutionContext.SuppressFlow();
ThreadPool.QueueUserWorkItem((Object obj) =>
Console.WriteLine(“(撤销ExecutionContext流动)ThreadPool线程中Name为:\”{0}\””,
CallContext.LogicalGetData(“Name”))); Thread.Sleep(500); //
复苏不引进使用ExecutionContext.RestoreFlow() flowControl.Undo();
ThreadPool.QueueUserWorkItem((Object obj) =>
Console.WriteLine(“(恢复生机ExecutionContext流动)ThreadPool线程中Name为:\”{0}\””,
CallContext.LogicalGetData(“Name”))); Thread.Sleep(500);
Console.WriteLine(); // 叁)
在眼下线程上的钦点执行上下文中运营某些方法。(通过获得调用上下文数听他们证明)
Console.WriteLine(“3)在脚下线程上的内定执行上下文中运营有些方法。(通过取得调用上下文数据印证)”);
ExecutionContext curExecutionContext = ExecutionContext.Capture();
ExecutionContext.SuppressFlow(); ThreadPool.QueueUserWorkItem( (Object
obj) => { ExecutionContext innerExecutionContext = obj as
ExecutionContext; ExecutionContext.Run(innerExecutionContext, (Object
state) =>
Console.WriteLine(“ThreadPool线程中Name为:\”{0}\””<br> ,
CallContext.LogicalGetData(“Name”)), null); } , curExecutionContext ); }
View Code

结果如图:

美高梅开户网址 9

 

 

 注意:

壹)        
示例中“在近日线程上的内定执行上下文中运作有些方法”:代码中必须使用ExecutionContext.Capture()获取当前施行上下文的3个副本

a)        
若直接行使Thread.CurrentThread.ExecutionContext则会报“十分小概利用以下上下文:
跨 AppDomains 封送的上下文、不是透过捕获操作获取的上下文或已作为 Set
调用的参数的上下文。”错误。

b)        
若使用Thread.CurrentThread.ExecutionContext.CreateCopy()会报“只好复制新近捕获(ExecutionContext.Capture())的上下文”。

2)        
撤消执行上下文流动除了使用ExecutionContext.SuppressFlow()方式外。仍是能够由此选拔ThreadPool的UnsafeQueueUserWorkItem

UnsafeRegisterWaitForSingleObject来进行委托方法。原因是不安全的线程池操作不会传导压缩堆栈。每当压缩堆栈流动时,托管的侧重点、同步、区域安装和用户上下文也随之流动。

 

线程池线程中的十分

线程池线程中未处理的百般将停止进度。以下为此规则的三种例外意况: 

  1. 是因为调用了 Abort,线程池线程少校吸引ThreadAbortException。 
    二.
    出高满堂值卸载应用程序域,线程池线程中校引发AppDomainUnloadedException。 
  2. 公物语言运转库或宿主进程将适可而止线程。

曾几何时不使用线程池线程

今昔我们都曾经知道线程池为我们提供了有益的异步API及托管的线程管理。那么是还是不是其他时候都应有使用线程池线程呢?当然不是,我们依然要求“因地制宜”的,在以下二种情形下,适合于创造并管理本身的线程而不是使用线程池线程:

 

 

  本博文介绍线程池以及其基础对象池,ThreadPool类的选择及注意事项,怎样排队办事项到线程池,执行上下文及线程上下文字传递递难题…… 

线程池尽管为我们提供了异步操作的有利,但是它不援助对线程池中单个线程的扑朔迷离控制致使我们有些意况下会一直动用Thread。并且它对“等待”操作、“打消”操作、“接二连三”任务等操作相比较繁琐,恐怕驱使你从新造轮子。微软也想开了,所以在.NET四.0的时候参预了“并行任务”并在.NET四.5中对其开始展览改进,想询问“并行任务”的园友能够先看看《(译)关于Async与Await的FAQ》。

本节到此截止,感激大家的欣赏。赞的话还请多引进啊 (*^_^*)

 

 

 

 

参考资料:《CL哈弗 via C#(第三版)》

 

 摘自:

 

异步编制程序:使用线程池管理线程 从此图中大家会发觉 .NET 与C#
的种种版本公布都以有八个大旨…

透过CL福特Explorer线程池所确立的线程总是暗中认可为后台线程,优先级数为ThreadPriority.Normal。

应用程序能够有五个线程,这几个线程在蛰伏状态中必要消耗多量岁月来等待事件发生。别的线程大概进入睡眠状态,并且仅定期被唤醒以轮循更改或更新景况音信,然后再一次进入休眠状态。为了简化对这个线程的管制,.NET框架为各样进度提供了3个线程池,二个线程池有好七个等待操作景况,当贰个等待操作达成时,线程池中的扶助线程会执行回调函数。线程池中的线程由系统管理,程序员不要求费劲于线程管理,能够集中精力处理应用程序任务。通过基础类库中的ThreadPool类提供五个线程池,该线程池可用以发送工作现,处理异步I/O,代表任何线程等待及处理计时器.ThreadPool类的拥有办法都以静态方法.ThreadPool自个儿也是二个静态类.
我们来探视她的定义和部分常用的措施:
 public
static class ThreadPool
{
 [SecuritySafeCritical]
        public static void
GetAvailableThreads(out int workerThreads, out int
completionPortThreads);
        [SecuritySafeCritical]
        public static void
GetMaxThreads(out int workerThreads, out int
completionPortThreads);
        [SecuritySafeCritical]
        public static void
GetMinThreads(out int workerThreads, out int
completionPortThreads);
        [SecuritySafeCritical]
        public static bool
QueueUserWorkItem(WaitCallback callBack);
        [SecuritySafeCritical]
        public static bool
QueueUserWorkItem(WaitCallback callBack, object state);
}
GetAvailableThreads这么些办法重临的最大线程池线程数和近来活动线程数之间的差值。
参数 workerThreads: 可用支持线程的数量。completionPortThreads: 可用异步
I/O 线程的数量。
Get马克斯Threads方法取稳当前由线程池维护的救助线程的最大数目.参数
workerThreads: 线程池中国救亡剧团助线程的最大数额。completionPortThreads:
当前由线程池维护的空余异步 I/O 线程的最大数据。
GetMinThreads方法取伏贴前由线程池维护的空闲支持线程的小小数目.参数
workerThreads:
当前由线程池维护的悠闲帮助线程的微小数目.completionPortThreads:
当前由线程池维护的闲暇异步 I/O 线程的细小数目。
QueueUserWorkItem方法将艺术排入队列以便执行。参数callBack,
表示要推行的方法.state:包蕴方法所用数据的靶子。
下边看个例子:

  在面向对象编制程序中,创制和销毁对象是很费时间的,因为创设3个目的要获取内部存款和储蓄器能源依旧其余越来越多能源,所以坚实服务程序效用的二个手腕正是尽可能收缩创设和销毁对象的次数,尤其是有的很耗电源的靶子创立和销毁。怎么样选择已有目的来服务正是一个亟待化解的关键难题,其实那正是壹些”池化能源”技术发生的原由。比如大家所熟识的数据库连接池正是根据那1想想而发出的,本文将介绍的线程池技术1样符合这一心想。

CLSportage线程池分为劳重力线程(workerThreads)I/O线程(completionPortThreads)两种:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading;
 6 
 7 namespace ConsoleApplication6
 8 {
 9     class Program
10     {
11         static void Main(string[] args)
12         {
13             Console.WriteLine("主线程进行异步条用");
14 
15             AutoResetEvent asyncOpIsDone = new AutoResetEvent(false);
16             ThreadPool.QueueUserWorkItem(new WaitCallback((x) =>
17             {
18 
19                 Thread.Sleep(1000);
20                 Console.WriteLine("工作任务");
21 
22             }));
23             string s="我的参数";
24             ThreadPool.QueueUserWorkItem(new WaitCallback((x) =>
25             {
26                
27                 Thread.Sleep(2000);
28                 Console.WriteLine("工作任务1");
29                 Console.WriteLine(x);
30                
31             }), s);
32             ThreadPool.QueueUserWorkItem(new WaitCallback(MyAsyncOperation), asyncOpIsDone);
33             Console.WriteLine("主线程执行其他");
34             Console.WriteLine("主线程等待任务处理结束");
35             asyncOpIsDone.WaitOne();
36         }
37         static void MyAsyncOperation(Object state)
38         {
39            
40             Thread.Sleep(5000);
41             Console.WriteLine("工作任务2");
42             ((AutoResetEvent)state).Set();
43         }
44     }
45 }

  • 劳重力线程是至关重要用作管理CL奇骏内部对象的运维,1般而言用于总计密集的天职。
  • I/O(Input/Output)线程重大用来与外部系统互相消息,如输入输出,CPU仅需在任务开端的时候,将职分的参数字传送递给配备,然后运转硬件设备即可。等职务到位的时候,CPU收到三个通报,1般的话是一个硬件的刹车复信号,此时CPU继续后继的处理工科作。在处理进度中,CPU是无须完全加入处理进程的,若是正在运行的线程不交出CPU的控制权,那么线程也只能处于等候景况,尽管操作系统将最近的CPU调度给任何线程,此时线程所占用的上空依旧被占用,而并未CPU处理这些线程,大概出现线程能源浪费的题目。假设这是多少个网络服务程序,每叁个互联网连接都利用2个线程管理,大概出现大批量线程都在守候互连网通信,随着互联网连接的不停加码,处于等候状态的线程将会很成本尽全部的内部存款和储蓄器能源。能够设想使用线程池化解那一个题材。

 

  10二线程是怎样?组成?特点?

  线程池的最大值壹般默许为一千、三千。当不止此数额的伸手时,将保证排队状态,直到线程池里有线程可用。

 运营的结果为

  线程池是1种八线程处理情势,处理进程少将任务添加到行列,然后在创造线程后活动运营这一个任务。线程池中的线程由系统一管理理,程序员不要求费劲于线程管理,能够集中精力处理应用程序职责。

  使用CL君越线程池的劳力线程一般有二种格局:

美高梅开户网址 10

  组成:服务器程序利用线程技术响应客户请求已经数见不鲜,大概你认为那样做效用已经很高,但您有未有想过优化一下运用线程的法子。该小说将向你介绍服务器程序怎么样利用线程池来优化品质并提供四个简练的线程池完成。

  • 通过ThreadPool.QueueUserWorkItem()方法;
  • 透过信托;

此间有个类为AutoReset伊夫nt,他的效能是通报正在等候的线程已产惹祸件。他是从伊夫ntWaitHandle继承而来的!例子中分头用了二种分歧的办法调用,第两种是足以传递参数的!工作线程一就传递了”小编的参数”字符串!工作线程二运作完了会通报等待的线程已产生事件.那里AutoReset伊芙nt开端化的时候首先将时域信号设成false,工作线程三头要调用成功,将被设成true. asyncOpIsDone.WaitOne()阻塞当前线程,直到收到时限信号!

  一、线程池管理器(ThreadPoolManager):用于创建并管理线程池

  要注意,不论是由此ThreadPool.QueueUserWorkItem()依旧委托,调用的都以线程池里的线程。

再看下边包车型地铁例子

  贰、工作线程(WorkThread): 线程池中线程

因此以下四个措施可以读取和装置CLTiguan线程池四川中华工程集团我线程与I/O线程的最大线程数。

 

  3、任务接口(Task):每一个职责必须达成的接口,以供工作线程调度职分的进行。

  1. ThreadPool.GetMax(out in workerThreads,out int
    completionPortThreads);
  2. ThreadPool.SetMax(int workerThreads,int completionPortThreads);

 

  四、义务队列:用于存放未有处理的天职。提供壹种缓冲机制。

  若想测试线程池中有稍许线程正在投入使用,能够经过ThreadPool.GetAvailableThreads(out
in workThreads,out int conoletionPortThreads)方法。

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading;
 6 
 7 namespace ConsoleApplication7
 8 {
 9     class Program
10     {
11         static void Main(string[] args)
12         {
13             Console.WriteLine("\n当前线程的HashCode:{0}", Thread.CurrentThread.GetHashCode().ToString());
14             Console.WriteLine("当前应用域的名字为:{0}", AppDomain.CurrentDomain.FriendlyName);
15             int workerThreads;
16             int completionPortThreads;
17 
18             AutoResetEvent asyncOpIsDone = new AutoResetEvent(false);//信号初始为空
19             AutoResetEvent asyncOpIsDone2 = new AutoResetEvent(false);
20             ThreadPool.QueueUserWorkItem(new WaitCallback(MyWork), asyncOpIsDone);
21             ThreadPool.QueueUserWorkItem(new WaitCallback(MyWork1), asyncOpIsDone2);
22             ThreadPool.GetMaxThreads(out workerThreads, out completionPortThreads);
23             Console.WriteLine("得当前由线程池维护的辅助线程的最大数目:{0}", workerThreads);
24             ThreadPool.GetMinThreads(out workerThreads, out completionPortThreads);
25             Console.WriteLine("得当前由线程池维护的空闲辅助线程的最小数目:{0}", workerThreads);
26             /*WaitHandle[] waithandles = new WaitHandle[2];
27             waithandles[0] = asyncOpIsDone;
28             waithandles[1] = asyncOpIsDone2;
29             WaitHandle.WaitAll(waithandles);  */     
30             //或者可以这样
31             asyncOpIsDone.WaitOne();
32             Console.WriteLine("MyWork结束");
33             asyncOpIsDone2.WaitOne();
34             Console.WriteLine("MyWork1结束");
35         }
36         static void MyWork(Object state)
37         {
38             Console.WriteLine("\n当前线程的HashCode:{0}", Thread.CurrentThread.GetHashCode().ToString());
39             Console.WriteLine("当前应用域的名字为:{0}", AppDomain.CurrentDomain.FriendlyName);
40             Thread.Sleep(2000);
41             ((AutoResetEvent)state).Set();//表示工作已经完成
42         }
43         static void MyWork1(Object state)
44         {
45             Console.WriteLine("\n当前线程的HashCode:{0}", Thread.CurrentThread.GetHashCode().ToString());
46             Console.WriteLine("当前应用域的名字为:{0}", AppDomain.CurrentDomain.FriendlyName);
47             Thread.Sleep(1000);
48             ((AutoResetEvent)state).Set();//表示工作已经完成
49         }
50 
51     }
52 }

 

方法 说明
GetAvailableThreads 剩余空闲线程数
GetMaxThreads 最多可用线程数,所有大于此数目的请求将保持排队状态,直到线程池线程变为可用
GetMinThreads 检索线程池在新请求预测中维护的空闲线程数
QueueUserWorkItem 启动线程池里得一个线程(队列的方式,如线程池暂时没空闲线程,则进入队列排队)
SetMaxThreads 设置线程池中的最大线程数
SetMinThreads 设置线程池最少需要保留的线程数

 

  特点:

我们能够使用线程池来解决地方的超越百分之五10题材,跟使用单个线程比较,使用线程池有如下优点:

运维结果为

  • 3个经过有且唯有2个线程池。
  • 线程池线程都今后台线程(即不会阻止进度的结束)
  • 每种线程都选取私下认可堆栈大小,以暗许的优先级运行,并处在10二线程单元中。超过最大值的任何线程必要排队,但它们要等到别的线程达成后才开动。
  • 在CLPAJERO 2.0 SP一此前的版本中,线程池中 默许最大的线程数量 = 处理器数 *
    二5, CL奥迪Q5 二.0 SP壹之后就成为了 私下认可最大线程数量 = 处理器数 *
    250,线程上限能够变动,通过运用ThreadPool.Get马克斯+Threads和ThreadPool.Set马克斯Threads方法,能够赢得和设置线程池的最大线程数。
  • 暗中同意意况下,各种处理器维持2个空余线程,即暗中同意最小线程数 =
    处理器数。
  • 当进度运行时,线程池并不会活动创设。当第壹回将回调方法排入队列(比如调用ThreadPool.QueueUserWorkItem方法)时才会成立线程池。
  • 在对1个行事项实行排队之后将不能收回它。
  • 线程池中线程在形成职务后并不会自行销毁,它会以挂起的情事再次来到线程池,假诺应用程序再度向线程池发出请求,那么这么些挂起的线程将激活并施行职务,而不会创建新线程,这将节约了过多支付。唯有线程达到最大线程数量,系统才会以一定的算法销毁回收线程。

壹、缩小应用程序的响应时间。因为在线程池中有线程的线程处于等候分配职责状态(只要没有当先线程池的最大上限),无需创建线程。

 


贰、不必管理和拥戴生活周期短暂的线程,不用在创立刻为其分配财富,在其推行完职分之后自由能源。

美高梅开户网址 11

  如几时候使用线程池?**  **

叁、线程池会依照如今系统本性对池内的线程进行优化处理。

本例中能够详细看AutoRest伊夫nt的用法MyWork一事实上先截止的,可是asyncOpIsDone需求等MyWork的时域信号!所以先输出了MyWork结束.那里还有七个东西小编想说的就是WaitHandle,下面的例子已经付出了他的用法!他是AutoRsetEvent的基类.

  一、必要多量的线程来形成义务,且做到职务的时间比较短。
WEB服务器实现网页请求那样的天职,使用线程池技术是可怜适合的。因为单个义务小,而任务数量巨大,你能够想象一个吃香网址的点击次数。
但对于长日子的天职,比如3个Telnet连接请求,线程池的亮点就不显然了。因为Telnet会话时间比线程的创立即间基本上了。

总的说来使用线程池的功用就是收缩创造和销毁线程的系统开发。在.NET中有1个线程的类ThreadPool,它提供了线程池的军事管制。

还有ThreadPool有2个函数RegisterWaitForSingleObject那个函数依然满有意思的!笔者那边就不再给出例子了!

  贰、对品质供给苛刻的行使,比如必要服务器快捷响应客户请求。

ThreadPool是一个静态类,它从未构造函数,对外提供的函数也全体是静态的。在那之中有三个QueueUserWorkItem方法,它有二种重载方式,如下:

好了,明天就到那了!

  3、接受突发性的雅量请求,但未必使服务器因此发生多量线程的运用。突发性多量客户请求,在未曾线程池意况下,将发生多量线程,固然理论上多数操作系统线程数目最大值不是题材,短期内爆发大批量线程也许使内部存款和储蓄器到达终点,并冒出”OutOfMemory”的一无可取。

public static bool QueueUserWorkItem(WaitCallback
callBack):将艺术排入队列以便执行。此措施在有线程池线程变得可用时实施。

    

public static bool QueueUserWorkItem(WaitCallback
callBack,Object
state):将艺术排入队列以便执行,并点名包蕴该方法所用数据的目的。此办法在有线程池线程变得可用时实施。

  什么样时候不适合使用线程池?

QueueUserWorkItem方法中利用的的WaitCallback参数表示3个delegate,它的申明如下:

  

public delegate void WaitCallback(Object
state)

  ●若是须要使七个职务具有一定优先级

1经急需传递职责新闻能够利用WaitCallback中的state参数,类似于ParameterizedThreadStart委托。

  ●假设全数极大概率会长期运作(并为此阻塞其余职分)的职责

上面是二个ThreadPool的例子,代码如下:

  ●要是急需将线程放置到单线程单元中(线程池中的线程均处于拾二线程单元中)

美高梅开户网址 12美高梅开户网址 13

  ●若是急需永久标识来标识和控制线程,比如想行使专用线程来终止该线程,将其挂起或按名称发现它。

using System;
using System.Collections;
using System.ComponentModel;
using System.Diagnostics;
using System.Threading;

namespace ConsoleApp1
{
    class ThreadPoolDemo
    {
        public ThreadPoolDemo()
        {
        }

        public void Work()
        {
            ThreadPool.QueueUserWorkItem(new WaitCallback(CountProcess));
            ThreadPool.QueueUserWorkItem(new WaitCallback(GetEnvironmentVariables));
        }
        /// <summary>  
        /// 统计当前正在运行的系统进程信息  
        /// </summary>  
        /// <param name="state"></param>  
        private void CountProcess(object state)
        {
            Process[] processes = Process.GetProcesses();
            foreach (Process p in processes)
            {
                try
                {
                    Console.WriteLine("进程信息:Id:{0},ProcessName:{1},StartTime:{2}", p.Id, p.ProcessName, p.StartTime);
                }
                catch (Win32Exception e)
                {
                    Console.WriteLine("ProcessName:{0}", p.ProcessName);
                }
                finally
                {
                }
            }
            Console.WriteLine("获取进程信息完毕。");
        }
        /// <summary>  
        /// 获取当前机器系统变量设置  
        /// </summary>  
        /// <param name="state"></param>  
        public void GetEnvironmentVariables(object state)
        {
            IDictionary list = System.Environment.GetEnvironmentVariables();
            foreach (DictionaryEntry item in list)
            {
                Console.WriteLine("系统变量信息:key={0},value={1}", item.Key, item.Value);
            }
            Console.WriteLine("获取系统变量信息完毕。");
        }
    }
}

ThreadPoolDemo

  线程池常用艺术介绍?

美高梅开户网址 14美高梅开户网址 15

  

using System;
using System.Threading;

namespace ConsoleApp1
{

    class Program
    {
        static void Main(string[] args)
        {
            ThreadPoolDemo tpd1 = new ThreadPoolDemo();
            tpd1.Work();
            Thread.Sleep(5000);
            Console.WriteLine("OK");
            Console.ReadLine();
        }
    }
}

  一、Get马克斯Threads()    :
 获取可以同时处于活动状态的线程池请求的最大数额。全部大于此数额的伸手将维持排队状态,直到线程池线程变为可用。

Program

    •   函数原型:public static void GetMaxThreads (out int
      workerThreads,out int completionPortThreads)

 

                  参数1:workerThreads
:线程池中支持线程的最大数额。 
                  参数二:completionPortThreads :线程池中异步 I/O
线程的最大数额。 

使用ThreadPool调用工作线程和IO线程的范例

 

美高梅开户网址 16美高梅开户网址 17

  ②、GetMinThreads()    获取线程池维护的小不点儿空闲线程数。        

using System;
using System.Collections;
using System.IO;
using System.Text;
using System.Threading;

namespace ConsoleApp1
{

    class Program
    {
        static void Main(string[] args)
        {
            // 设置线程池中处于活动的线程的最大数目
            // 设置线程池中工作者线程数量为1000,I/O线程数量为1000
            ThreadPool.SetMaxThreads(1000, 1000);
            Console.WriteLine("Main Thread: queue an asynchronous method");
            PrintMessage("Main Thread Start");

            // 把工作项添加到队列中,此时线程池会用工作者线程去执行回调方法            
            ThreadPool.QueueUserWorkItem(asyncMethod);
            asyncWriteFile();
            Console.Read();
        }

        // 方法必须匹配WaitCallback委托
        private static void asyncMethod(object state)
        {
            Thread.Sleep(1000);
            PrintMessage("Asynchoronous Method");
            Console.WriteLine("Asynchoronous thread has worked ");
        }


        #region 异步读取文件模块
        private static void asyncReadFile()
        {
            byte[] byteData = new byte[1024];
            FileStream stream = new FileStream(@"D:\123.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite, 1024, true);
            //把FileStream对象,byte[]对象,长度等有关数据绑定到FileDate对象中,以附带属性方式送到回调函数
            Hashtable ht = new Hashtable();
            ht.Add("Length", (int)stream.Length);
            ht.Add("Stream", stream);
            ht.Add("ByteData", byteData);

            //启动异步读取,倒数第二个参数是指定回调函数,倒数第一个参数是传入回调函数中的参数
            stream.BeginRead(byteData, 0, (int)ht["Length"], new AsyncCallback(Completed), ht);
            PrintMessage("asyncReadFile Method");
        }

        //实际参数就是回调函数
        static void Completed(IAsyncResult result)
        {
            Thread.Sleep(2000);
            PrintMessage("asyncReadFile Completed Method");
            //参数result实际上就是Hashtable对象,以FileStream.EndRead完成异步读取
            Hashtable ht = (Hashtable)result.AsyncState;
            FileStream stream = (FileStream)ht["Stream"];
            int length = stream.EndRead(result);
            stream.Close();
            string str = Encoding.UTF8.GetString(ht["ByteData"] as byte[]);
            Console.WriteLine(str);
            stream.Close();
        }
        #endregion

        #region 异步写入文件模块
        //异步写入模块
        private static void asyncWriteFile()
        {
            //文件名 文件创建方式 文件权限 文件进程共享 缓冲区大小为1024 是否启动异步I/O线程为true
            FileStream stream = new FileStream(@"D:\123.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite, 1024, true);
            //这里要注意,如果写入的字符串很小,则.Net会使用辅助线程写,因为这样比较快
            byte[] bytes = Encoding.UTF8.GetBytes("你在他乡还好吗?");
            //异步写入开始,倒数第二个参数指定回调函数,最后一个参数将自身传到回调函数里,用于结束异步线程
            stream.BeginWrite(bytes, 0, (int)bytes.Length, new AsyncCallback(Callback), stream);
            PrintMessage("AsyncWriteFile Method");
        }

        static void Callback(IAsyncResult result)
        {
            //显示线程池现状
            Thread.Sleep(2000);
            PrintMessage("AsyncWriteFile Callback Method");
            //通过result.AsyncState再强制转换为FileStream就能够获取FileStream对象,用于结束异步写入
            FileStream stream = (FileStream)result.AsyncState;
            stream.EndWrite(result);
            stream.Flush();
            stream.Close();
            asyncReadFile();
        }
        #endregion

        // 打印线程池信息
        private static void PrintMessage(String data)
        {
            int workthreadnumber;
            int iothreadnumber;

            // 获得线程池中可用的线程,把获得的可用工作者线程数量赋给workthreadnumber变量
            // 获得的可用I/O线程数量给iothreadnumber变量
            ThreadPool.GetAvailableThreads(out workthreadnumber, out iothreadnumber);

            Console.WriteLine("{0}\n CurrentThreadId is {1}\n CurrentThread is background :{2}\n WorkerThreadNumber is:{3}\n IOThreadNumbers is: {4}\n",
                data,
                Thread.CurrentThread.ManagedThreadId,
                Thread.CurrentThread.IsBackground.ToString(),
                workthreadnumber.ToString(),
                iothreadnumber.ToString());
        }
    }
}
  • 函数原型:public static void GetMinThreads (out int
    workerThreads,out int completionPortThreads)
    参数一:workerThreads:当前由线程池维护的悠闲辅助线程的细微数目。 
    参数二:completionPortThreads:当前由线程池维护的悠闲异步 I/O
    线程的小不点儿数目。 

Program

 

 

  三、SetMaxThreads()  
 设置能够同时处于活动状态的线程池的最大请求数目(不考虑总括机处理器的多少)

线程池中放入异步操作

    • 函数原型:public static bool SetMinThreads (int
      workerThreads,intcompletionPortThreads)

美高梅开户网址 18美高梅开户网址 19

             
 参数一:workerThreads::要由线程池维护的新的极小空闲补助线程数。 
             
 参数贰:completionPortThreads::要由线程池维护的新的纤维空闲异步 I/O
线程数。 
               重临值:如若改动成功,则为 true;不然为 false。 

using System;
using System.Threading;

namespace ConsoleApp1
{

    class Program
    {
        private static void AsyncOperation(object state)
        {
            Console.WriteLine("Operation state: {0}", state ?? "(null)");
            Console.WriteLine("Worker thread id: {0}", Thread.CurrentThread.ManagedThreadId);
            Thread.Sleep(TimeSpan.FromSeconds(2));
        }

        static void Main(string[] args)
        {
            const int x = 1;
            const int y = 2;
            const string lambdaState = "lambda state 2";

            ThreadPool.QueueUserWorkItem(AsyncOperation);
            Thread.Sleep(TimeSpan.FromSeconds(1));

            ThreadPool.QueueUserWorkItem(AsyncOperation, "async state");
            Thread.Sleep(TimeSpan.FromSeconds(1));

            ThreadPool.QueueUserWorkItem(state => {
                Console.WriteLine("Operation state: {0}", state);
                Console.WriteLine("Worker thread id: {0}", Thread.CurrentThread.ManagedThreadId);
                Thread.Sleep(TimeSpan.FromSeconds(2));
            }, "lambda state");

            ThreadPool.QueueUserWorkItem(_ =>
            {
                Console.WriteLine("Operation state: {0}, {1}", x + y, lambdaState);
                Console.WriteLine("Worker thread id: {0}", Thread.CurrentThread.ManagedThreadId);
                Thread.Sleep(TimeSpan.FromSeconds(2));
            }, "lambda state");

            Thread.Sleep(TimeSpan.FromSeconds(2));
        }
    }
}

 

Program

  四、SetMinThreads()    
设置线程池在新请求预测中维护的空闲线程数(不惦记总括机处理器的多少)

 

    • 函数原型:public static bool SetMinThreads (int
      workerThreads,intcompletionPortThreads)

线程池同步操作

             
 参数壹:workerThreads:要由线程池维护的新的相当小空闲协理线程数。 
             
 参数二:completionPortThreads:要由线程池维护的新的纤维空闲异步 I/O
线程数。 
               再次回到值:倘若改变成功,则为 true;不然为 false。 

美高梅开户网址 20美高梅开户网址 21

  

using System;
using System.Threading;

namespace ConsoleApp1
{
    class ThreadPoolDemo
    {
        static object lockobj = new object();
        static int Count = 0;
        ManualResetEvent manualEvent;
        public ThreadPoolDemo(ManualResetEvent manualEvent)
        {
            this.manualEvent = manualEvent;
        }
        public void DisplayNumber(object a)
        {

            lock (lockobj)
            {
                Count++;
                Console.WriteLine("当前运算结果:{0},Count={1},当前子线程id:{2} 的状态:{3}", a, Count, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.ThreadState);
            }
            //Console.WriteLine("当前运算结果:{0}", a);
            //Console.WriteLine("当前运算结果:{0},当前子线程id:{1} 的状态:{2}", a,Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.ThreadState);
            //这里是方法执行时间的模拟,如果注释该行代码,就能看出线程池的功能了
            Thread.Sleep(2000);
            //Console.WriteLine("当前运算结果:{0},Count={1},当前子线程id:{2} 的状态:{3}", a, Count, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.ThreadState);
            //这里是释放共享锁,让其他线程进入
            manualEvent.Set();


        }
    }
}

  5、GetAvailableThreads()    获取由 Get马克斯Threads
再次来到的线程池线程的最大数据和近日运动数量之间的差值。    

ThreadPoolDemo

    • 函数原型:public static void GetAvailableThreads (out int
      workerThreads,out int completionPortThreads)

美高梅开户网址 22美高梅开户网址 23

                参数1:workerThreads:可用帮忙线程的数码。 
                参数二:completionPortThreads:可用异步 I/O 线程的多寡。 

using System;
using System.Diagnostics;
using System.Threading;

namespace ConsoleApp1
{

    class Program
    {
        //设定任务数量 
        static int count = 10;
        static void Main(string[] args)
        {
            //让线程池执行5个任务所以也为每个任务加上这个对象保持同步
            ManualResetEvent[] events = new ManualResetEvent[count];
            Console.WriteLine("当前主线程id:{0}", Thread.CurrentThread.ManagedThreadId);

            Stopwatch sw = new Stopwatch();
            sw.Start();
            NoThreadPool(count);
            sw.Stop();
            Console.WriteLine("Execution time using threads: {0}", sw.ElapsedMilliseconds);


            sw.Reset();
            sw.Start();
            //循环每个任务
            for (int i = 0; i < count; i++)
            {
                //实例化同步工具
                events[i] = new ManualResetEvent(false);
                //Test在这里就是任务类,将同步工具的引用传入能保证共享区内每次只有一个线程进入
                ThreadPoolDemo tst = new ThreadPoolDemo(events[i]);
                //Thread.Sleep(200);
                //将任务放入线程池中,让线程池中的线程执行该任务                 
                ThreadPool.QueueUserWorkItem(tst.DisplayNumber, i);
            }
            //注意这里,设定WaitAll是为了阻塞调用线程(主线程),让其余线程先执行完毕,
            //其中每个任务完成后调用其set()方法(收到信号),当所有
            //的任务都收到信号后,执行完毕,将控制权再次交回调用线程(这里的主线程)
            ManualResetEvent.WaitAll(events);
            sw.Stop();
            Console.WriteLine("Execution time using threads: {0}", sw.ElapsedMilliseconds);
            //Console.WriteLine("所有任务做完!");
            Console.ReadKey();
        }

        static void NoThreadPool(int count)
        {
            for (int i = 0; i < count; i++)
            {
                Thread.Sleep(2000);
                Console.WriteLine("当前运算结果:{0},Count={1},当前子线程id:{2} 的状态:{3}", i, i + 1, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.ThreadState);
            }
        }

    }
}

 

Program

  6、QueueUserWorkItem()  
 将艺术排入队列以便执行。此办法在有线程池线程变得可用时举办。 

 

    • 重载方法一:public static bool QueueUserWorkItem (WaitCallback
      callBack)

线程池中的撤废操作

                重返值:如若将艺术成功排入队列,则为 true;不然为
false。 

美高梅开户网址 24美高梅开户网址 25

    • 重载方法二:public static bool QueueUserWorkItem (WaitCallback
      callBack,Object state)
using System;
using System.Threading;

namespace ConsoleApp1
{

    class Program
    {
        static void Main(string[] args)
        {
            ThreadPool.SetMaxThreads(1000, 1000);
            Console.WriteLine("Main thread run");
            PrintMessage("Start");
            Run();
            Console.ReadKey();
        }

        private static void Run()
        {
            CancellationTokenSource cts = new CancellationTokenSource();

            // 这里用Lambda表达式的方式和使用委托的效果一样的,只是用了Lambda后可以少定义一个方法。
            // 这在这里就是让大家明白怎么lambda表达式如何由委托转变的
            ////ThreadPool.QueueUserWorkItem(o => Count(cts.Token, 1000));
            ThreadPool.QueueUserWorkItem(callback, cts.Token);

            Console.WriteLine("Press Enter key to cancel the operation\n");
            Console.ReadLine();

            // 传达取消请求            
            cts.Cancel();
            Console.ReadLine();
        }

        private static void callback(object state)
        {
            Thread.Sleep(1000);
            PrintMessage("Asynchoronous Method Start");
            CancellationToken token = (CancellationToken)state;
            Count(token, 1000);
        }

        // 执行的操作,当受到取消请求时停止数数
        private static void Count(CancellationToken token, int countto)
        {
            for (int i = 0; i < countto; i++)
            {
                if (token.IsCancellationRequested)
                {
                    Console.WriteLine("Count is canceled");
                    break;
                }

                Console.WriteLine(i);
                Thread.Sleep(300);
            }

            Console.WriteLine("Cout has done");
        }

        // 打印线程池信息
        private static void PrintMessage(String data)
        {
            int workthreadnumber;
            int iothreadnumber;

            // 获得线程池中可用的线程,把获得的可用工作者线程数量赋给workthreadnumber变量
            // 获得的可用I/O线程数量给iothreadnumber变量
            ThreadPool.GetAvailableThreads(out workthreadnumber, out iothreadnumber);

            Console.WriteLine("{0}\n CurrentThreadId is {1}\n CurrentThread is background :{2}\n WorkerThreadNumber is:{3}\n IOThreadNumbers is: {4}\n",
                data,
                Thread.CurrentThread.ManagedThreadId,
                Thread.CurrentThread.IsBackground.ToString(),
                workthreadnumber.ToString(),
                iothreadnumber.ToString());
        }
    }
}

               参数2:state :包罗方法所用数据的对象。 
               再次回到值:假诺将艺术成功排入队列,则为 true;不然为
false。 
      备注:WaitCallback
回调方法必须与System.Threading.WaitCallback委托项目相匹配。

Program

         WaitCallback函数原型:public delegate void
WaitCallback(Object state);调用QueueUserWorkItem可以通过Object来向职务进度传递参数。固然职分进度须要七个参数,能够定义包蕴这个数据的类,并将类的实例强制转换为Object数据类型。

 

 

Thread与ThreadPool的三个属性比较

  7、UnsafeQueueUserWorkItem()    非安全性注册二个守候 WaitHandle
的信托(将艺术排入队列以便执行)。

美高梅开户网址 26美高梅开户网址 27

    • 函数原型:public static bool UnsafeQueueUserWorkItem
      (WaitCallback callBack,Object state)     
      //不将调用堆栈传播到赞助线程上。那允许代码失去调用堆栈,从而提高了它的平安特权。
    • 备注:使用
      UnsafeQueueUserWorkItem
      恐怕会无形中中开拓四个安全漏洞。代码访问安全性的权杖检查依照全体调用方对堆栈的权力实行。若是使用
      UnsafeQueueUserWorkItem
      将工作排在有个别线程池线程上,则该线程池线程的库房将不会有所实际调用方的背景。恶意代码恐怕会动用那一点避开权限检查。
using System;
using System.Diagnostics;
using System.Threading;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            const int numberOfOperations = 300;
            var sw = new Stopwatch();
            sw.Start();
            UseThreads(numberOfOperations);
            sw.Stop();
            Console.WriteLine("Execution time using threads: {0}", sw.ElapsedMilliseconds);

            sw.Reset();
            sw.Start();
            UseThreadPool(numberOfOperations);
            sw.Stop();
            Console.WriteLine("Execution time using threadPool: {0}", sw.ElapsedMilliseconds);
        }

        static void UseThreads(int numberOfOperations)
        {
            using (var countdown = new CountdownEvent(numberOfOperations))
            {
                Console.WriteLine("Scheduling work by creating threads");
                for (int i = 0; i < numberOfOperations; i++)
                {
                    var thread = new Thread(() => {
                        Console.Write("{0},", Thread.CurrentThread.ManagedThreadId);
                        Thread.Sleep(TimeSpan.FromSeconds(0.1));
                        countdown.Signal();
                    });
                    thread.Start();
                }
                countdown.Wait();
                Console.WriteLine();
            }
        }

        static void UseThreadPool(int numberOfOperations)
        {
            using (var countdown = new CountdownEvent(numberOfOperations))
            {
                Console.WriteLine("Starting work on a threadpool");
                for (int i = 0; i < numberOfOperations; i++)
                {
                    ThreadPool.QueueUserWorkItem(_ => {
                        Console.Write("{0},", Thread.CurrentThread.ManagedThreadId);
                        Thread.Sleep(TimeSpan.FromSeconds(0.1));
                        countdown.Signal();
                    });
                }
                countdown.Wait();
                Console.WriteLine();
            }
        }
    }
}

 

Program

  八、RegisterWaitForSingleObject()    
将钦命的委托排队到线程池。当发生以下景况之近日,援助线程将进行委托。

 

  玖、UnsafeRegisterWaitForSingleObject()  
非安全性将点名的委托排队到线程池。

 


 

  线程池示例?

 

  大家先来看四个简短的线程实例:

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Begin in Main");
            Thread t = new Thread(ThreadInvoke);
            t.IsBackground = true;
            t.Start();

            //将当前线程挂起200毫秒
            Thread.Sleep(200);
            Console.WriteLine("End in Main");
            Console.ReadKey();
        }

        static void ThreadInvoke(object obj)
        {
            for (int i = 0; i < 5; i++)
            {
                Console.WriteLine("Execute in ThreadInvoke");
                //每隔100毫秒,循环一次
                Thread.Sleep(100);
            }
        }
    }
}

美高梅开户网址 28

 

“End in Main”并不曾在ThreadInvoke()方法中有着代码执行完事后才输出。

综上说述Main方法和ThreadInvoke是并行执行的

 

  使用线程池改造上面的示范:

    上边介绍了只是1个最简便易行的关于线程线程的例子,但在实际付出中运用的线程往往是大度的和尤其复杂的,那时,每便都成立线程、运行线程。从性质上来讲,那样做并不特出(因为每使用几个线程就要创造3个,供给占用系统开发);从操作上来讲,每便都要运行,相比较艰苦。为此引入的线程池的定义。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Begin in Main");
            ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadInvoke));
            Console.WriteLine("End in Main");
            //将当前线程挂起200毫秒
            Thread.Sleep(3000);

            Console.ReadKey();
        }

        static void ThreadInvoke(object obj)
        {
            for (int i = 0; i < 5; i++)
            {
                Console.WriteLine("Execute in ThreadInvoke");
                //每隔100毫秒,循环一次
                Thread.Sleep(100);
            }
        }
    }
}

 

Thread.Sleep(三千)那句话是必须的因为当Main方法甘休后,.Net环境会自行终止销毁线程池,为了确认保障完毕线程池里的任务,所以主线程必要等待一段时间。 

由输出结果能够,Main方法和ThreadInvoke方法是并行执行的。

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图