线程池编程技术

2018-11-05   阅读:107

  下面的例子申明了用一旦FileStream BeginWrite方式写文件操做竣事,线程池中的一个回调函数将会被施行。由于取框架集成正在一路,所以框架中的大部门类都供给了利用线程池的内正在功能,给开辟人员供给了集中办理和监督使用中的线程池的功能。class MainApp{ static void Main() { HttpWebRequest request;例如当线程池正在施行两个请求时,而CPU的操纵率才达到50%,这表白施行请求正期待某个事务或者正正在做某种I/O操做。好比 .NET Remoting 用它来处置来自近程对象的请求。正在HttpWebRequest这个类中,这个成对的方式就是:BeginGetResponse 和EndGetResponse。正在这个示例中,我们将异步成立一个毗连到当地的Web办事器,然后发送一个Get请求。倒霉的是,这将永久不会发生,由于利用线程池的函数正期待队列函数的竣事。pc.CheckIt();内容引见.NET中的线程池线程池中施行的函数利用按时器同步对象的施行异步I/O操做监督线程池死锁相关平安性竣事 引见 若是你有正在任何编程言语下的多线程编程经验的话,你必定曾经很是熟悉一些典型的典范。fs.Close();当此中任何一个请求处置竣事后,空闲的线程就会去提取第三个请求并处置之。我们能够用GetMaxThreads前往这个值:public static void GetMaxThreads( out int workerThreads, out int completionPortThreads);我的建议是仅正在机能很是主要的、平安曾经节制好的极端环境下才用非平安版本。IPEndPoint ipEndPoint=new IPEndPoint(ipHostEntry.AddressList[0], 80);大都使用系统需要读磁盘,数据发送到Sockets,因特网毗连等等。using System.Net。

  由于函数本身显示了可用的线程数量,所以我们能够通过这个来查看,对应的完成端口数曾经削减了几多。可是,我们现正在需要当一个操做竣事时从Web办事器前往的响应,为了领受到这个消息,.NET中所有供给异步操做的类都供给了成对的方式。假设一个使用没有权限拜候磁盘,可是它挪用了一个对整个系统都能够拜候的类库,当第二个法式集施行一个磁盘的操做时,设置到这个法式集的权限答应如许做,可是权限不会被使用到从叫法式集,.NET不只要查抄当出息序集的权限,并且会查抄整个挪用栈的权限。默认环境下,你的使用被设置装备摆设为答应施行磁盘操做,所以系统成功生成文件。这就是说,正在用户权限的范畴内,我们能够限制任何施行单位(法式集)利用的资本。把API和异步对象联系关系起来,用少量的资本和无效的方式,我们就能够挪用系统线程池的异步I/O操做。

  } static void PooledFunc(object state) { Console.WriteLine("Processing request {0}", (string)state);Console.ReadLine();.NET 成立正在统一个池上是一个很主要的功能特征。FileStream fs;我们有了较高的CPU操纵率。ConnectionSocket connection=new ConnectionSocket();这是由于.NET框架为我们维护了一个挪用栈才使它成为了可能,虽然建立文件的库有权限去拜候系统。假如你看过ThreadPool类的所无方法,你将发觉没有一个答应我们更改最大数的方式。

  } static void UserCallback(IAsyncResult ar) { Console.Write("Operation finished: {0} on thread ID:{1}, is pool: {2}", ar.IsCompleted, Thread.CurrentThread.GetHashCode(), Thread.CurrentThread.IsThreadPoolThread);现正在看一看这个输出成果:Main thread. Is pool thread: False, Hash: 2Processing request Is there any screw left?. Is pool thread: True, Hash: 4Processing request How much is a 40W bulb?. Is pool thread: True, Hash: 8Processing request Decrease stock of monkey wrench . Is pool thread: True, Hash: 9Request processedRequest processedRequest processed 你能够看到所有的请求都被系统线程池中的分歧线程施行。对于第一个参数(callback),我们能够指定按时施行的函数;答应施行用户函数,按时器,I/O操做和同步对象。IAsyncResult ar;监督线程池ThreadPool 类供给了两个方式用来查询线程池的形态。正在这种场景中,系统不需要为每个请求建立和销毁线程。下面的例子用别的一个支撑异步操做的类,HttpWebRequest。为了避免这些问题,.NET框架的线程池供给了独立于时间的请求。Console.ReadLine();举个例子,假如用户能够删除他公司内的任何共享文件,任何从Internet下载的法式也都能够如许做。因为长短平安版本不会维护它们施行函数之间的挪用栈,所以非平安版本运转的更快些。激励第三方组件利用线程池,如许它们的客户就能够享受.NET所供给的全数功能。Console.WriteLine("Synchronous: {0}", ar.CompletedSynchronously);} Console.ReadLine();若是方针线程属于线程池,这个属性将前往True。i++) { ThreadPool.QueueUserWorkItem(new WaitCallback(PoolFunc));鄙人面的例子中,我们将用System.Threading.Timer 类,按时器的最简单实现,我们只需要如下定义的构制方式public Timer(TimerCallback callback, object state, int dueTime, int period);s.EndConnect(ar);namespace ThreadSecurityTest{ class MainApp { static void Main() { PoolCheck pc=new PoolCheck()。

  别的,基于动静的实现并不长短常切确,假如你的使用法式正正在处置其它动静,环境有可能更蹩脚。鄙人面的代码片段中,我们利用了这个类来申明问题:class MainApp{ static void Main() { for(int i=0;第二个参数是传送给函数的通用对象;ThreadPool.QueueUserWorkItem(callBack, "Is there any screw left?");class MainApp{ static void Main() { const string fileName="temp.dat";假如25个函数都期待异步对象操做的竣事。挪用BeginConnect使异步操做正在线程池中施行,而EndConnect一曲堵塞到毗连被成立。s.BeginConnect(ipEndPoint, new AsyncCallback(ConnectCallback),s);} static void PoolFunc(IAsyncResult ar) { HttpWebRequest request;结论就是:我们的使用系统曾经堵塞了。3. 一旦毗连成立了,Socket类挪用指明的函数ConnectCallback,这个回调函数显示了线程池中可用的线程数量。}}多快,多好。

  现正在打开使命办理器,看一看CPU的利用率,你将看到使用法式拥有了CPU的100%的利用率。ThreadPool类供给了下面的方式:public static RegisteredWaitHandle RegisterWaitForSingleObject( WaitHandle waitObject, WaitOrTimerCallback callBack, object state, int millisecondsTimeOutInterval, bool executeOnlyOnce);Console.ReadLine()!

  当这两个函数同时正在池中施行时,线程池曾经没有用于其它请求的空间了,除非曲到某个函数竣事。若是你想正在你的使用中避免呈现死锁,永久不要堵塞正正在期待线程池中的其它函数的线程。现正在把库中的QueueUserWorkItem替代为UnsafeQueueUserWorkItem,再次编译法式集,然后运转Main法式。让我们连系这些新概念,看看“硬件商铺”的另一个实现。所有的这些操做都有一些特征,曲到他们施行操做时,才需要CPU时间。线程池中施行的函数ThreadPool.QueueUserWorkItem 方式运转我们正在系统线程池上启动一个函数,它的声明如下:public static bool QueueUserWorkItem (WaitCallback callBack, object state)第一个参数指明我们将正在池中施行的函数,它的声明必需取WaitCallback代办署理(delegate)互相婚配:public delegate void WaitCallback (object state);线程池答应我们把请求进行列队,曲到某个特殊的同步对象收到信号后施行。这个类只是封拆了Win32中动静机制的计数器,若是你不预备开辟多线程使用,那么就能够用这个类。你该当晓得的很主要的一点就是,Socket类老是会操纵最优的可用机制,所以你正在开辟使用时,能够不消考虑方针平台是什么。相反的,若是CPU操纵率达到100%,线程池能够削减线程的数量以获得更多的CPU时间,而不要华侈正在上下文切换上面。一个传送给函数的形态(state);using System.Threading;} }} 若是你正在Microsoft Windows NT, Windows 2000, or Windows XP 下运转这个法式,你将会看到如下成果:Connected to localhost:80WorkerThreads: 24, CompletionPortThreads: 25Request sent to localhost:80WorkerThreads: 25, CompletionPortThreads: 24 如你所看到地那样,毗连用了工做线程,而发送数据用了一个完成端口(CompletionPort),接着看下面的挨次:1. 我们获得一个当地IP地址,然后异步毗连到那里。多线程编程手艺使基于用户界面的使用更完满。Timer timer2=new Timer(new TimerCallback(OnTimer), 2, 0, 3000);若是我们正在Windows 95, Windows 98, 或者 Windows Me平台上运转不异的代码,会呈现不异的毗连成果,请求将被发送到工做线程,而非完成端口。再次运转这个例子,留意系统CPU的操纵率,若是你没有任何其它使用法式正在后台运转的话,它几乎是0%。

  第三个参数是计时器起头施行前的延时;残剩的参数答应我们指明当一个对象收到信号后施行的函数(callBack);由于系统独一正正在做的是每施行2秒后就挂起的处置。Console.WriteLine("Synchronous operation: {0}", ar.CompletedSynchronously);} void OnTimer() { Console.WriteLine("OnTimer");鄙人面例子中,你能够看到用UnsafeQueueUserWorkItem方式的风险。摘要深度摸索 Microsoft .NET供给的线程池, 揭示什么环境下你需要用线程池以及 .NET框架下的线程池是若何实现的,并告诉你若何去利用线程池。}}输出:Timer: 1 Thread: 2 Is pool thread: TrueTimer: 2 Thread: 2 Is pool thread: TrueTimer: 1 Thread: 2 Is pool thread: TrueTimer: 2 Thread: 2 Is pool thread: TrueTimer: 1 Thread: 2 Is pool thread: TrueTimer: 1 Thread: 2 Is pool thread: TrueTimer: 2 Thread: 2 Is pool thread: True犹如你看到的那样,两个按时器中的所有函数挪用都正在统一个线程中施行(ID=2),使用法式利用的资本最小化了。response=(HttpWebResponse)request.EndGetResponse(ar);Console.ReadLine()!

  现正在我们有.NET 供给的线程池,我们能够从池中改变请求的期待函数,如许就十分无效,并且会提拔系统的机能。第一个参数,waitObject 能够是任何承继于WaitHandle的对象: Mutex ManualResetEvent AutoResetEvent就像你看到的那样,只要系统的同步对象才能用正在这里,就是承继自WaitHandle的对象。这类系统的典型特征是大量的拜候会导致响应时间呈指数级增加和很高的CUP利用时间。我们能够通过正在两个方式中插手如下的代码,以此看到更多的消息。犹如你看到的那样,这个实现的成本会很是高。.NET中的线程池 基于上面的例子,正在企业级使用系统中有一个高效施行的线程池是至关主要的。} static void PoolFunc(object state) { int workerThreads,completionPortThreads;hostEntry=Dns.Resolve(Dns.GetHostName());凡是,多线程编程取基于用户界面的使用联系正在一路,它们需要正在不影响终端用户的环境下,施行一些耗时的操做。这节包含一个利用Socket 类的例子。} Console.WriteLine();你能够想象一下,办事器没有任何的用户界面,若是不消多线程手艺你将若何去实现?办事端通过通道(http, sockets, files 等等)领受来自客户端的请求并处置它们,然后发送一个应对到客户端。}}若是你运转这个例子,你将看到池中的线程是若何把线程的可用数量削减到零的,接着使用中止,死锁呈现了。记住一个金牌法则: 仅正在你的代码不答应让其它的使用系统挪用,或者当你想要严酷限制拜候很明白清晰的法式集,才利用非平安的函数。using System.Net.Sockets;通过这个例子,我们能够很容易地辨别这两种分歧的线程。仅仅是由于我们想晓得曾经做了异步请求。这很是有帮于理解上述两个类取别的一个称为System.Windows.Forms.Timer.的类。

  显式的用户请求(QueueUserWorkItem方式),基于异步对象的方式(RegisterWaitForSingleObject)和按时器(Timer类) CompletionPortThreads这种线程常常用来I/O操做,Windows NT, Windows 2000 和 Windows XP供给了一个步施行的对象,叫做IOCompletionPort。int ticks=Environment.TickCount;IPAddress ipAddress;我们用一个“硬件商铺”的客户/办事器使用系统做为例子。这个方案如下图所示: 图3:启用线程池的办事端使用系统正在这个例子中,我们用了一个含有两个线程的线程池。这类系统的一个遍及特征就是低CPU操纵时间导致呈现很长的响应时间,以至是正在拜候压力很大的情况里也如许。若是参数 timeout 设置的最大时间曾经失效,可是没有同步对象收到信号的花,这个函数就会被挪用。Main thread:9Synchronous operation: FalseOperation finished: True on thread ID:10, is pool: True正在使用Sockets的场景中,因为I/O操做凡是比磁盘操做慢,这时用线程池就显得尤为主要。} static void OnTimer(object obj) { Console.WriteLine("Timer: {0} Thread: {1} Is pool thread: {2}", (int)obj, Thread.CurrentThread.GetHashCode(), Thread.CurrentThread.IsThreadPoolThread);IAsyncResult 供给了良多风趣的属性,好比:AsyncWaitHandle ,一旦操做完成,一个异步对象将会被通知。当一个托管使用法式起头施行时,运转时情况(runtime)供给一个线程池,它将正在代码第一次拜候时被建立。下图申明了这个过程: 图2:多线程办事端使用系统就像如图2所示的那样。若是你开辟的类库会被第三方使用法式中利用,那么你就不应当用这些方式,由于它们可能用你的库获取拜候系统资本的权限。图1显示了它是若何运做的。取出任何一本参考书,打开相关线程这一章:你能找到一个能正在你的用户界面中并行施行数学运算的多线程示例吗?我的目标不是让你扔掉你的书,不要如许做。

  你能够通过System.Threading 名称空间的Thread Pool 类来利用线程池,若是你查看一下这个类,就会发觉所有的成员都是静态的,并且没有公开的构制函数。} }}为了简化例子,我们正在Main 类中建立一个静态方式用于处置请求。为了简化这个例子,我们仅建立一个代码组联系关系到main使用。Mutex mtx=new Mutex(true);ThreadPool.GetAvailableThreads(out workerThreads, out completionPortThreads);并且若是线程池的施行高效的话,它能添加或删除线程以获得最优的机能。} static void SendCallback(IAsyncResult ar) { Console.WriteLine("Request sent to localhost:80");using System;Windows平安机制是关心资本。byte[] data=new Byte[10000];Console.WriteLine("Connected to localhost:80");一个最优的实现是分析前面两种方案而提出的概念----线程池(Thread Pool),当一个请求达到时,使用系统把置入领受队列,一组的线程从队列提取请求并处置之。假如你正在开辟办事器使用系统,只需有可能就正在你的请求处置系统中利用线程池?

  

线程池编程技术

  别的一点就是正在压力很大的情况下,这三个线程会给系统带来良多的冲击。若是我们正在之前挪用EndGetResponse ,这个挪用将一曲堵塞到操做完成。Socket s=new Socket(ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);ThreadPool.GetAvailableThreads(out workerThreads, out completionPortThreads);// Simulation of processing time Thread.Sleep(2000);我们能够看到这些是正在工做线程中施行的。下面的例子建立了两个按时器,timer1和timer2:class MainApp{ static void Main() { Timer timer1=new Timer(new TimerCallback(OnTimer), 1, 0, 2000);为了完全理解这些方式,起首,我们必需回忆 .NET框架中平安策略是怎样运做的。利用按时器假如你已经开辟过Microsoft Win32的使用法式,你晓得SetTimer函数是API之一,通过这个函数能够指定的一个窗口领受到来自系统时间周期的WM_TIMER动静。mtx.ReleaseMutex();5. Socket上的发送和领受操做能够通过IOCompletionPort 来施行异步操做,所以当请求做完后,回调函数就会正在一个CompletionPort类型的线程中施行。HttpWebResponse response;}}class MyTimer{ int m_period!

  再看一下我们法式的输出成果:Processing request Is there any screw left?. Is pool thread: True, Hash: 7Processing request How much is a 40W bulb?. Is pool thread: True, Hash: 8Request processedProcessing request Decrease stock of monkey wrench . Is pool thread: True, Hash: 7Request processedRequest processed 留意第三个请求是正在第一个请求处置竣事之后施行的,并且线程的号码仍然用本来的7,这个缘由是线程池检测到CPU的利用率曾经达到100%,一曲期待某个线程空闲。死锁正在你的使用法式利用线程池之前,还有一个工具你该当晓得:死锁。} private void UserItem(object obj) { FileStream fs=new FileStream("test.dat", FileMode.Create);当一个新的请求达到之后,办事端为进入的请求建立一个新线程,施行竣事时,再销毁它。假设线程的施行操做不复杂,因为需要花额外的时间去建立和销毁线程,所以最终会严沉影响系统的响应时间。即便它曾经不再像本来的那样慢了,但建立线和销毁程也不是最得当的方式。Console.ReadLine();可是正在Windows 95, Windows 98, 和 Windows Me有一些局限。

  // Pool method Console.WriteLine("Processing request {0}." + " Is pool thread: {1}, Hash: {2}", (string)state, Thread.CurrentThread.IsThreadPoolThread, Thread.CurrentThread.GetHashCode());ThreadPool.RegisterWaitForSingleObject(evt, new WaitOrTimerCallback(PoolFunc), null, Timeout.Infinite, true);它并不会从头建立一个新的线程,如许就会削减线程间的上下文切换开销,以使总体机能更佳。这种方式遍及用于很多现有的系统,可是如许做系统的资本操纵率很低。用了这个函数,我们能够不消任何线程就能够具有成千上万个按时器,一旦时间片失效,这时,线程池将会处置这些请求。我们来点窜一下这个使用,此次我们不挂起处置请求的线程,相反我们会一曲让系统忙,为了做到这点,我们用Environment.TickCount. 建立一个每隔两秒就对请求施行一次的轮回。} }}第二个法式集援用了第一个,而且用了CheckIt 方式去建立一个文件:using System;图1显示了三个请求同时达到,但只要此中的一个被办事端处置。最初一个参数period,是两个施行之间的毫秒数。using System.Threading;public MyTimer(int period) { Thread thread;最初一个参数很是风趣,我们该当对异步施行文件的操做设置useAsync为True?

  // Main method Console.WriteLine("Main thread. Is pool thread: {0}, Hash: {1}", Thread.CurrentThread.IsThreadPoolThread, Thread.CurrentThread.GetHashCode());UnsafeQueueUserWorkItem , UnsafeRegisterWaitForSingleObject取 QueueUserWorkItem , RegisterWaitForSingleObject两个方式雷同。Console.WriteLine("WorkerThreads: {0}, CompletionPortThreads: {1}", workerThreads, completionPortThreads);s=new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);一旦到了最大的数量,就不会建立新线程,所有的请求都将被列队。因为代办署理的矫捷性,我们能够指定任何实例方式去向理请求,只需这些方式的声明取代办署理不异。callBack=new WaitCallback(PooledFunc);ipEndPoint=new IPEndPoint(ipAddress, 80);按照分歧的方针平台,.NET 框架会决定能否利用IOCompletionPorts API,用起码的资本达到最好的机能。相关平安性 若是你再看看ThreadPool类,你会看到有两个方式我们没有用到,UnsafeQueueUserWorkItem 和UnsafeRegisterWaitForSingleObject。using System.Threading;IAsyncResult ar=s.BeginConnect(ipEndPoint, null, null);request=(HttpWebRequest)ar.AsyncState;留意我们能够正在任何时候拜候IAsyncResult接口,它能够用来领会当前操做的形态。while(Environment.TickCount - ticks < 2000)。

  但线程池一曲是满的,所以请求就一曲期待任何空闲线程的呈现。namespace ThreadSecurityTest{ public class PoolCheck { public void CheckIt() { ThreadPool.QueueUserWorkItem(new WaitCallback(UserItem), null);你曾经看到正在上面的例子中每品种型的线程可用的最大数是25。Thread.Sleep(1000);using System;这个池取使用法式所正在运转的物理历程联系关系正在一路,当你用.NET框架下的统一历程中运转多个使用法式的功能特征时(称之为使用法式域),这将是一个很主要的细节。}}下面刚起头成果消息表白,异步操做正正在施行:Synchronous: False过了一会儿,响应领受到了。thread.Start();现实上, Microsoft .NET框架支撑正在任何言语编写的窗口下使用多线程编程手艺,答应开辟人员设想很是丰硕的界面,供给给终端用户一个更好的体验。我们能够用CompletedSynchronously 属性指示一个异步操做能否完成,而当一个操做竣事时,IsCompleted 属性会设上一个值。线程池期待对象的最大时间 (millisecondsTimeOutInterval) 和一个标识表白对象收到信号时函数只能施行一次, (executeOnlyOnce). 下面的代办署理声明目标是用正在函数的回调:delegate void WaitOrTimerCallback( object state, bool timedOut);.NET 供给了使用到法式的平安性策略,而不是用户。这是有来由如许做的,由于每个历程只要一个线程池,而且我们不克不及建立新的。成果将是一样的,死锁一样会呈现。若是你的使用法式利用了多个按时器,相对的线程数量也会跟着利用按时器的数量而增加。代码如下: class ConnectionSocket{ public void Connect() { IPHostEntry ipHostEntry=Dns.Resolve(Dns.GetHostName());Console.WriteLine("Main thread:{0}", Thread.CurrentThread.GetHashCode())。

  用这个方式碰到的第一个问题是你需要一个窗口去领受动静,所以你不克不及用正在节制台使用法式中。为了让这个功能运转起来,.NET 框架必需维护一个分歧法式集之间的挪用栈。正在上面最初一个示例中,我们没有用到从操做中前往的成果。别的一个策略就是正在当前的系统中为每一个请求建立分歧的线程。正在这种环境下,因为它们都利用同样的线程池,一个坏的使用法式会影响历程中的其它使用法式。鄙人面的例子中,我们发送一个请求到Microsoft Web,然后显示了领受到响应的大小。看一看FileStream 的构制方式是若何利用的:public FileStream( string path, FileMode mode, FleAccess access, FleShare share, int bufferSize, bool useAsync);这个线程池不只对使用法式可用,并且还融合到框架中的大都类中。下面的例子用了一个手工事务和一个互斥量来通知线程池中的施行函数:class MainApp{ static void Main(string[] args) { ManualResetEvent evt=new ManualResetEvent(false);我们进修了一个线程池是若何实现的,需要考虑多个要素如:CPU利用的百分比,队列请求或者系统的处置器数量。线程池能够发觉这种环境,并添加线程的数量以使系统能正在统一时间处置更多的请求。Console.WriteLine("File created")。

  这看起来很容易,但记住这个法则意味着有两条:n 不要建立如许的类,它的同步方式正在期待异步函数。.NET供给了丰硕的线程池的功能以让我们的使用法式利用, 而且取.NET框架的类慎密地集成正在一路。多个线程同时施行请求处置将导致CPU的操纵率达到100%,并且大大都时间会华侈正在上下文切换过程中,以至会跨越处置请求的本身。}}这个代码一般用于Wn32使用中。正在这里你能够看到.NET框架的最大特色:一次编译,能够正在多个系统下运转。图1: 单线程的办事端使用系统为了让客户端的请求不会脱漏,办事端使用系统实现了某种队列来存放这些请求。当办事端起头施行 "Decrease stock of monkey wrench," 这个请求时,其它两个必需正在队列中期待。connection.Connect()!

  } void TimerThread() { Thread.Sleep(m_period);ThreadPool.QueueUserWorkItem(callBack, "How much is a 40W bulb?");s.BeginSend(data, 0,data.Length,SocketFlags.None, new AsyncCallback(SendCallback), null);i++) { Console.Write("{0}...", i);data=Encoding.ASCII.GetBytes("GET /\n");通过MMC,我们能够按照前提定义一组法式集,然后为每组设置分歧的策略,一个典型的例子就是限制从Internet下载的法式拜候磁盘的权限。using System.Text;你不克不及用其它任何的同步机制,好比moniter 或者 read-write 锁。这种方式代替了对每个客户端毗连都启用一个线程的做法,所有的操做都正在线程池中异步施行。若是我们没有线程,或者线程必需堵塞曲到事务收到信号,就像我前面提到一样,这会添加使用法式中总的线程数量,成果导致系统需要更多的资本和CPU时间。我们以此揣度25个线程的线程池的行为。ShowAvailableThreads();以下代码显示了这个手艺的一种实现:class MainApp{ static void Main() { MyTimer myTimer=new MyTimer(2000);ipAddress=hostEntry.AddressList[0]?

  request=(HttpWebRequest)WebRequest.CreateDefault( new Uri(""));for(int i=1;Console.WriteLine("Request processed");n 不要正在任何异步函数中利用如许的类,若是它正期待着这个异步函数。} static void ShowAvailableThreads() { int workerThreads, completionPortThreads;这个线程池是高度优化了的,它只需要起码的CPU时间和资本,并且总能顺应方针平台。我们添加了一个Thread.CurrentThread.IsThreadPoolThread的挪用。i<=5;用这个类,我们能够成立一个到Web办事器的毗连。ar=fs.BeginWrite(data, 0, 10000, new AsyncCallback(UserCallback), null);} static void ConnectCallback(IAsyncResult ar) { byte[] data;using System.IO;从方式中你能够看到两种分歧的线程: WorkerThreads 工做线程是尺度系统池的一部门。虽然能够正在任何时间挪用EndGetResponse 方式,但正在我们的例子中是正在回调函数中做的。它们是被.NET框架托管的尺度线程,大都函数是正在这里施行的。你该当查抄你的代码,以确定哪个正在线程中施行的函数正正在期待异步操做,然后删除它。例如,你建立的使用法式不会被其它的法式集挪用,或者仅被很明白清晰的法式集利用,那么你能够用非平安版本。

  namespace ThreadPoolTest{ class MainApp { static void Main() { WaitCallback callBack;Console.ReadLine();同样的缘由,公共言语运转时的宿从也有可能去更改这个设置装备摆设。竣事 正在这篇文章中,我们晓得了为什么正在我们的办事器使用中需要利用线程池来优化资本和CPU的操纵。若是线程池中的一个施行函数顶用了这个类的方式,将会发生什么工作呢?设想线程池的大小只要两个线程,然后用我们的毗连类建立了两个异步对象。4. 正在用ASCII码对Get请求进行编码后,我们用BeginSend方式从同样的函数ConnectCallback 中发送一个异步请求。2. Socket正在工做线程上施行异步毗连操做,由于正在Socket上,不克不及用Windows 的IOCompletionPorts来成立毗连。这种方式对使用系统的用户认证很是无效,但当呈现用户对他利用的系统发生不信赖的环境时,这就会有些局限性。namespace ThreadPoolTest{ class MainApp { static void Main() { Socket s;IPHostEntry hostEntry;这个栈曾经被高度优化了,可是它们给两个分歧法式集之间的挪用添加了额外的承担。特别是正在办事器使用法式中施行多线程异步操做,机能会更好。好比:ASP.NET答应系统办理员更改这个数字。当第一个施行完成后,接着是第二个,以此类推。这就是为什么不成能让使用法式域去更改这个设置装备摆设的缘由。同步对象的施行相对于按时器,.NET线程池答应正在施行函数上同步对象,为了正在多线程情况中的各线程之间共享资本,我们需要用.NET同步对象。ar=request.BeginGetResponse(new AsyncCallback(PoolFunc), request)。

  设想你的代码中有个方式,它需要通过Socket毗连到一个Web办事器上。i<30;假设 “decreasing the stock”请求点窜磁盘上的一个文件,而这个文件正正在被点窜中,CPU将不会被利用,即便这个请求正处正在待处置阶段。由于这品种可能被线程池中的线程挪用。正在这种环境下,一旦用户安拆了这个法式,它就能够施行用户权限范畴内的任何操做。ThreadPool.RegisterWaitForSingleObject(mtx, new WaitOrTimerCallback(PoolFunc), null, Timeout.Infinite, true);IPEndPoint ipEndPoint;线程之间能互相操纵。thread=new Thread(new ThreadStart(TimerThread))。

  fs=new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None, 1, true);客户端是收银机,办事端是运转正在仓库里一台独立的机械上的使用系统。Socket s=(Socket)ar.AsyncState;Microsoft正在.NET框架的开辟情况中曾经实现了这个,该系统的焦点供给了一个现成可用的最优线程池。第一个是我们能够从线程池获取当前可用的线程数量:public static void GetAvailableThreads( out int workerThreads, out int completionPortThreads);就像我们前面提到的那样,线程池是每个处置过程的独一共享资本。每个按时器建立独立的线程,而且期待指定的时间,然后呼叫回调函数。} static void PoolFunc(object obj, bool TimedOut) { Console.WriteLine("Synchronization object signaled, Thread: {0} Is pool: {1}", Thread.CurrentThread.GetHashCode(), Thread.CurrentThread.IsThreadPoolThread);问题是这些函数挪用了我们类中的Connect方式,这个方式正在线程池中又倡议了一个异步操做。别的,我们还显示了用GetHashCode 方式从当火线程前往的成果。可是回调函数将只正在当出息序集的平安策略下施行,它就不克不及使用权限到整个挪用栈中的法式集。它是独一标识当前施行线程的值。OnTimer();Console.WriteLine(" Response size: {0}", response.ContentLength);Console.ReadLine();IAsyncResult ar;ThreadPool.QueueUserWorkItem(callBack, "Decrease stock of monkey wrench");过程跟前面提到的差不多,Socket 类供给了多个方式用于施行异步操做: BeginRecieve BeginSend BeginConnect BeginAccept假如你的办事器使用利用了Socket来取客户端通信,必然会用到这些方式。我们将建立两个零丁的法式集,正在第一个法式集中我们将正在线程池中建立一个文件,然后我们将导出一个类以使这个操做能够被其它的法式集施行。

  现正在的成果是:File created即便我们的系统没有脚够的权限去拜候磁盘,但我们曾经建立了一个向整个系统公开它的功能的库,却没有维护它的挪用栈。File created现正在,打开.NET框架的设置装备摆设。Console.WriteLine("Response received on pool: {0}", Thread.CurrentThread.IsThreadPoolThread);.NET 框架为所有这些可能施行的异步操做供给了I/O类。你若是编译和施行这个典范,将会看到下面的输出:Processing request Is there any screw left?Processing request How much is a 40W bulb?Processing request Decrease stock of monkey wrenchRequest processedRequest processedRequest processed 留意,所有的请求都被分歧的线程并行处置了。相对基于Win32的按时器来说, .NET 中一个很主要的改良就是建立分歧的线程,该线程堵塞指定的时间,然后通知一个回调函数。这个方式叫BeginGetResponse, 但正在这个例子中有一个很主要的区别。这些特色呈现正在两个分歧的类中: System.Threading.Timer 按时器的简单版本,它运转开辟人员向线程池中的按期施行的法式指定一个代办署理(delegate).System.Timers.TimerSystem.Threading.Timer的组件版本,答应开辟人员把它拖放到一个窗口表单(form)中,能够把一个事务做为施行的函数。若是我们没有如许做,即便我们用了异步函数,它们的操做仍然会被从叫线程堵塞。运转使用法式,看看会发生什么环境:Unhandled Exception: System.Security.SecurityException: Request for the permission of type System.Security.Permissions.FileIOPermission, mscorlib, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 failed.我们的策略起头工做,系统曾经不克不及建立文件了。正在这里典范中,通过挪用Thread.Sleep,实现延迟两秒以模仿处置时间。下面的成果显示:Response received on pool: True Response size: 27331就像你看到的那样,一旦收到响应,线程池的异步函数就会施行。当三个请求达到时,它们立即放置到队列期待被处置,由于两个线程都是空闲的,所以头两个请求起头施行。或者你开辟了一个让办事器法式利用的库,那么尽可能供给系统线程池的异步对象处置。这里的按时器不需要Microsoft的动静系统,所以如许就更切确,并且还能用于节制台使用法式中。一个可能的实现就是用Socket 类中的BeginConnect方式异步打开一个毗连,然后用EndConnect方式期待毗连的成立。

  Console.ReadLine();线程的可用数量曾经没有而且CPU的利用率为0 ,这是很较着的死锁症状。n 假如建立了多个按时器,线程池会由于期待它们时间片失效而很是忙。正在领导中,选择Hash 前提并导入Hash到我们的使用中,设置为Internet 级别,并选择“该策略级别将只具有取此代码组联系关系的权限集中的权限”选项。可是,多线程编程手艺不只仅是为了用户界面的使用,正在没有任何用户界面的使用中,一样会呈现多个施行流的环境。例如这些法式是从Internet下载的!

  Thread.Sleep(15000);Console.WriteLine("WorkerThreads: {0}," + " CompletionPortThreads: {1}", workerThreads, completionPortThreads);好比: 正在某些设备上,没有供给IOCompletionPorts 功能和一些异步操做,如磁盘和邮件槽。} }}编译这两个法式集,然后运转main使用。若是这个信号没有收到,请求函数将不需要任何线程,所以能够包管系统机能最优化。所以我们不克不及具有一个通过第三方组建建立的无法办理的线程池。正在第一个例子中,我们将把一个文件异步写到硬盘中。操做系统本身答应对文件,用户,注册表键值和任何其它的系统资本设定权限。用了End版本,我们能够领受操做的成果。正在线程池中施行一个实现欠好的异步对象可能导致你的整个使用系统中止运转。

  接着展开 运转库平安策略/ 计较机/ 代码组/ All_Code /,添加一个叫ThreadSecurityTest的组。我们会碰到两个问题:n 假如线程池已满(所有的线程都正在运转中),那么这个请求排到队列中期待,并且按时器不正在切确。m_period=period;}}输出的成果显示了操做是异步施行的,一旦操做竣事后,用户的函数就正在线程池中施行。当这些操做施行完后,线程池中特定的函数会施行。using System;}}竣事显示两个函数都正在线程池的统一线程中施行:1...2...3...4...5...Synchronization object signaled, Thread: 6 Is pool: TrueSynchronization object signaled, Thread: 6 Is pool: True 异步I/O操做线程池常见的使用场景就是I/O操做。evt.Set();若是你想检测到使用中的死锁环境,那么就当你的系统挂起时,查抄线程池中的线程可用数!

  State 参数答应任何类型的消息传送到该方式中,它正在挪用QueueUserWorkItem时传入。ShowAvailableThreads();想象一下呈现这种环境的后果,若是有第三方组件把线程池中线程的最大数改为1,整个使用城市遏制工做,以至正在历程中其它的使用法式域都将遭到影响。这个限制的目标是为了把所有的异步编程手艺都集中到统一个池中。正在我们的示例中,EndGetResponse 会从Web办事器领受响应!

新媒体

新手程序员如何学习C语言编程
MFC:MFC手艺虽然听说前期一段时间冷下来了(近期又有新的热度,貌似融入了新的血液),可是进修者能熟练控制它,才能短期

高级编程技术(一)
1.3 《Python编程:从入门到实践》教材操练2-1至2-112-1 简单动静标题问题描述:将一条动静储存到变量中,再将其打印出来。

线程池编程技术
下面的例子申明了用一旦FileStream BeginWrite方式写文件操做竣事,线程池中的一个回调函数将会被施行。由于取框架集成正在一

Java多线程编程核心技术
前 言 第1章 Java多线程技术, 1.1 历程和多线程的概念及线程的长处 1.2 利用多线程 1.2.1 承继Thread类 1.2.2 实现Runnable接口 1.2