NETCF开发之线程池编程

线程池

.NET Compact Framework提供了几种不同的方法去创建多线程应用程序。而实现多线程最理想的方法可能得算使用线程池中已存在的线程。图23-2展示使用线程池中已存在的线程和直接创建线程在执行效率上的差别。

NETCF开发之线程池编程

<shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"><stroke joinstyle="miter"></stroke><formulas><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f></formulas><path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"></path><lock v:ext="edit" aspectratio="t"></lock></shapetype><shape id="_x0000_i1026" style="WIDTH: 155.25pt; HEIGHT: 207pt" type="#_x0000_t75"><imagedata o:title="" src="file:///D:%5CDOCUME~1%5CADMINI~1%5CLOCALS~1%5CTemp%5Cmsohtml1%5C01%5Cclip_image001.png"></imagedata></shape>

23-2:使用线程池和线程的比较

如图23-2所示的测试程序运行在普通的Windows CE .NET 4.2模拟器中,并创建200个生存期都很短的相互不同的工作线程。而实际上,所有工作线程的唯一功能是检查某个具体线程是否为第200个线程。在此情况下,设置一个外部事件来通知主线程已完成测试的运行,这样主线程就可以将计时信息显示在用户界面上。清单23-6是如图23-2所示的测试程序的实现代码。线程对应btnUseThread_Click过程,线程池对应btnUseThreadPool_Click过程。

清单23-6:比较线程池和线程的执行效率

<group id="_x0000_s1026" style="WIDTH: 414pt; HEIGHT: 686.4pt; mso-position-horizontal-relative: char; mso-position-vertical-relative: line" editas="canvas" coordorigin="2526,7642" coordsize="7200,11965"><lock v:ext="edit" aspectratio="t"></lock><shape id="_x0000_s1027" style="LEFT: 2526px; WIDTH: 7200px; POSITION: absolute; TOP: 7642px; HEIGHT: 11965px" o:preferrelative="f" type="#_x0000_t75"><font size="3"><fill o:detectmouseclick="t"></fill><path o:extrusionok="t" o:connecttype="none"></path><lock v:ext="edit" text="t"></lock></font></shape><rect id="_x0000_s1028" style="LEFT: 2526px; WIDTH: 7200px; POSITION: absolute; TOP: 7642px; HEIGHT: 11965px" fillcolor="#eaeaea" strokecolor="#eaeaea"><textbox style="mso-next-textbox: #_x0000_s1028"><table cellspacing="0" cellpadding="0" width="100%"><tbody><tr> <td style="BORDER-LEFT-COLOR: #d4d0c8; BORDER-BOTTOM-COLOR: #d4d0c8; BORDER-TOP-COLOR: #d4d0c8; BACKGROUND-COLOR: transparent; BORDER-RIGHT-COLOR: #d4d0c8"> <div> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman">Public Class ThreadPoolVSThread<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman"><span style="mso-spacerun: yes"> </span>Dim threadCounter As Integer<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman"><span style="mso-spacerun: yes"> </span>Dim threadPoolCounter As Integer<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman"><span style="mso-spacerun: yes"> </span>Dim doneEvent As Threading.AutoResetEvent<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman"><span style="mso-spacerun: yes"> </span>Private Sub btnUseThread_Click(ByVal sender As System.Object, _<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: 21pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman">ByVal e As System.EventArgs) Handles btnUseThread.Click<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman">threadCounter = 0<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman">doneEvent = New Threading.AutoResetEvent(False)<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman">lThreadResult.Text = ""<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman">Dim elapsedTime As Integer = Environment.TickCount<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman">Dim i As Integer<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman"><span style="mso-spacerun: yes"> </span><span style="mso-tab-count: 1"> </span>For i = 1 To 200<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman">Dim workerThread As Threading.Thread = _<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: 21pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman">New Threading.Thread(New Threading.ThreadStart(AddressOf MyWorkerThread))<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: 21pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman">workerThread.Start()<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman"><span style="mso-spacerun: yes"> </span><span style="mso-tab-count: 1"> </span>Next<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman"><span style="mso-spacerun: yes"> </span><span style="mso-tab-count: 1"> </span>doneEvent.WaitOne()<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman"><span style="mso-spacerun: yes"> </span><span style="mso-tab-count: 1"> </span>elapsedTime = Environment.TickCount - elapsedTime<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman"><span style="mso-spacerun: yes"> </span><span style="mso-tab-count: 1"> </span>lThreadResult.Text = "</font></span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">创建线程:</span><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman">" + elapsedTime.ToString() + " msec"<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman"><span style="mso-spacerun: yes"> </span>End Sub<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman"><span style="mso-spacerun: yes"> </span>Private Sub MyWorkerThread()<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman">threadCounter += 1<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman"><span style="mso-spacerun: yes"> </span><span style="mso-tab-count: 1"> </span>If (threadCounter = 200) Then<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: 21pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman">doneEvent.Set()<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman"><span style="mso-spacerun: yes"> </span><span style="mso-tab-count: 1"> </span>End If<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman"><span style="mso-spacerun: yes"> </span>End Sub<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman"><span style="mso-spacerun: yes"> </span>Private Sub btnUseThreadPool_Click(ByVal sender As System.Object, _<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: 21pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman">ByVal e As System.EventArgs) Handles btnUseThreadPool.Click<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman">threadPoolCounter = 0<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman"><span style="mso-spacerun: yes"> </span><span style="mso-tab-count: 1"> </span>doneEvent = New Threading.AutoResetEvent(False)<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman"><span style="mso-spacerun: yes"> </span><span style="mso-tab-count: 1"> </span>lThreadPoolResult.Text = ""<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman"><span style="mso-spacerun: yes"> </span><span style="mso-tab-count: 1"> </span>Dim elapsedTime As Integer = Environment.TickCount<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman"><span style="mso-spacerun: yes"> </span><span style="mso-tab-count: 1"> </span>Dim i As Integer<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman"><span style="mso-spacerun: yes"> </span><span style="mso-tab-count: 1"> </span>For i = 1 To 200<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: 21pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman">Threading.ThreadPool.QueueUserWorkItem( _<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 63pt; TEXT-INDENT: 21pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman">New Threading.WaitCallback(AddressOf MyWaitCallBack))<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman"><span style="mso-spacerun: yes"> </span><span style="mso-tab-count: 1"> </span>Next<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman"><span style="mso-spacerun: yes"> </span><span style="mso-tab-count: 1"> </span>doneEvent.WaitOne()<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman"><span style="mso-spacerun: yes"> </span><span style="mso-tab-count: 1"> </span>elapsedTime = Environment.TickCount - elapsedTime<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman"><span style="mso-spacerun: yes"> </span><span style="mso-tab-count: 1"> </span>lThreadPoolResult.Text = "</font></span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">创建线程:</span><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman">" + elapsedTime.ToString() + " msec"<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman"><span style="mso-spacerun: yes"> </span>End Sub<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman"><span style="mso-spacerun: yes"> </span>Private Sub MyWaitCallBack(ByVal stateInfo As Object)<span style="mso-spacerun: yes"> </span><p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman">threadPoolCounter += 1<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman">If (threadPoolCounter = 200) Then<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: 21pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman">doneEvent.Set()<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman"><span style="mso-spacerun: yes"> </span><span style="mso-tab-count: 1"> </span>End If<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman"><span style="mso-spacerun: yes"> </span>End Sub<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><font face="Times New Roman">End Class<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><p><font face="Times New Roman"></font></p></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><p><font face="Times New Roman"></font></p></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><p><font face="Times New Roman"></font></p></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 14pt; mso-line-height-rule: exactly"><span lang="EN-US" style="FONT-SIZE: 9pt"><p><font face="Times New Roman"></font></p></span></p> </div> </td> </tr></tbody></table></textbox></rect><wrap type="none"></wrap><anchorlock></anchorlock></group>

从图23-2所示界面的执行结果来看,使用线程池线程所占时间不到使用Thread线程所占时间的10%。原因是线程池中的线程是可重复使用的,从而消除创建新线程对象和设置其资源的系统开销。创建工作线程是一项系统开销较大的操作,也是导致性能差异的重要因素。线程池线程在需要时被创建,直至达到200的线程数量上线。当回调函数被终止时,线程池线程大约驻留线程池60秒以等待重用。如果在60秒内应用程序再次运行再次使用线程的话,这时线程池中存在足够的线程可被重用而无需创建新线程,因此大大提高了应用程序执行性能。实际上,线程池就是一个可重复使用的线程集合。

因为线程池线程是共享资源,所以不应该在线程池内运行长期的线程。如果调用 QueueUserWorkItem 方法时线程池中没有可用的线程,则要么在线程池中创建新线程要么等待直到线程池中的线程变得可用后才开始执行指定的委托(线程池中的全部线程均被使用时)。线程池线程是一个可以直接运行且实际存在的前台线程,需要在应用程序关闭之前将其正确终止,正确终止线程池线程的方法与普通线程类似。

你可能感兴趣的:(多线程,thread,编程,F#,ext)