你参看:
ms-help://MS.VSCC/MS.MSDNVS.2052/cpguide/html/cpconthreadpooling.htm
主要是RegisterWaitForSingleObject和QueueUserWorkItem两个静态方法

解决方案 »

  1.   

    我在msdn(2002,april)找不到你说的地址.
    贴给我好么?
      

  2.   

    我的问题:
    1。threadPool怎么管理线程的,一般的pool好像都有共享某一资源的概念,比如数据库连接pool,threadPool也是吗?从宏观看是否有多个线程同时在pool内运行?
    2。是否每次调用RegisterWaitForSingleObject和QueueUserWorkItem都创建一个新的线程?RegisterWaitForSingleObject是通过event阻塞,QueueUserWorkItem是怎么阻塞的,我看了几个例子,都是运行一个很普通的函数,是不是函数结束线程再pool也结束了。
      

  3.   

    .NET 框架开发者指南   线程池  [C#]请参见
    线程处理对象和功能 | ThreadPool 类 | 线程与线程处理 | I/O 异步完成 | Timer
    语言
    C#Visual Basic全部显示
    可以使用线程池来根据应用程序的需要更为有效地利用多个线程。许多应用程序使用多个线程,但这些线程经常在休眠状态中耗费大量的时间来等待事件发生。其他线程可能进入休眠状态,并且仅定期被唤醒以轮询更改或更新状态信息,然后再次进入休眠状态。使用线程池就可以为应用程序提供一个由系统管理的辅助线程池,从而使您可以集中精力于应用程序任务而不是线程管理。实际上,如果要执行一些需要多个线程的较短任务,则使用 ThreadPool 类是利用多个线程的最方便且最好的方法。使用线程池使系统能够不仅针对此进程而且针对计算机上的其他进程(您的应用程序对其一无所知)对此情况进行优化以达到更好的吞吐量。使用线程池使系统能够在考虑到计算机上的所有当前进程后对线程时间片进行优化。.NET 框架出于以下几个目的使用线程池:异步调用、System.Net 套接字连接、异步 I/O 完成以及计时器与注册的等待操作等等。通过从托管代码调用 ThreadPool.QueueUserWorkItem(或者从非托管代码调用 CorQueueUserWorkItem)并传递用来包装要添加到队列中的方法的 WaitCallback 委托来使用线程池。也可以通过使用 ThreadPool.RegisterWaitForSingleObject 并传递 WaitHandle(在向其发出信号或超时时,它将引发对由 WaitOrTimerCallback 委托包装的方法的调用)来将与等待操作相关的工作项排队到线程池中。在这两种情况下,线程池都使用或创建一个后台线程来调用回调方法。如果您知道调用方的堆栈与在排队任务执行期间执行的所有安全检查不相关,则还可以使用不安全的方法 ThreadPool.UnsafeQueueUserWorkItem 和 ThreadPool.UnsafeRegisterWaitForSingleObject。QueueUserWorkItem 和 RegisterWaitForSingleObject 都会捕获调用方的堆栈,此堆栈将在线程池线程开始执行任务时合并到线程池线程的堆栈中。如果需要进行安全检查,则必须检查整个堆栈。尽管此检查提供了安全,但它还具有一定的性能开销。使用“不安全的”方法调用并不会提供绝对的安全,但它会提供更好的性能。在应用程序域中只有一个 ThreadPool 对象,并且在您首次调用 ThreadPool.QueueUserWorkItem 时或者当计时器或已注册的等待操作将某一回调方法排队时,将创建线程池。一个线程监视所有已排队到线程池中的任务。当某项任务完成后,线程池中的线程将执行相应的回调方法。在对一个工作项进行排队之后将无法取消它。可以排队到线程池中的操作的数目仅受可用内存的限制;但是,线程池将对允许在进程中同时处于活动状态的线程数目强制实施限制(这取决于 CPU 的数目和其他因素)。每个线程都使用默认堆栈大小,以默认的优先级运行,并处于多线程单元中。如果某个线程在托管代码中空闲(如正在等待某个事件),则线程池将插入另一个辅助线程来使所有处理器保持繁忙。如果所有线程池线程都始终保持繁忙,但队列中包含挂起的工作,则线程池将在一段时间之后创建另一个辅助线程。但线程的数目永远不会超过最大值。在执行 ThreadPool 回调时,ThreadPool 还切换到正确的 AppDomain。在若干种情况下,适合于创建并管理自己的线程而不是使用 ThreadPool。您应在以下几种情况下创建并管理自己的线程: 如果您需要使一个任务具有特定的优先级。 
    如果您具有可能会长时间运行(并因此阻塞其他任务)的任务。 
    如果您需要将线程放置到单线程单元中(所有 ThreadPool 线程均处于多线程单元中)。 
    如果您需要与该线程关联的稳定标识。例如,您可能想使用专用线程来中止该线程、将其挂起或按名称发现它。 
    下面的代码示例同时使用了 QueueUserWorkItem 和 RegisterWaitForSingleObject 方法。前者用于在每次循环时两次请求对 ThreadFunc 方法的调用。后者用于将 AutoResetEvent 注册到 ThreadPool。然后,就会在某次循环中向 AutoResetEvent 发出信号,而 ThreadPool 将分配一个线程来调用 WaitThreadFunc。[Visual Basic]
    Imports System
    Imports System.ThreadingPublic Class Sensor
       Private Shared A As Integer = 32
       Private Shared S As [String] = "Initial string"
       
       Public Shared Sub Main()
          
          Dim ev As New AutoResetEvent(False)
          ThreadPool.RegisterWaitForSingleObject(ev, New WaitOrTimerCallback(AddressOf WaitThreadFunc), Nothing, 20000, False)
          
          Dim count As Integer
          
         
          For count = 1 To 5 
             Console.WriteLine("Hello everyone!!")
             Console.WriteLine("{0}, {1}", A, S)
             
             ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf ThreadFunc), count)
             ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf ThreadFunc), count + 1)
             
             ' Signal the AutoResetEvent, which raises the ThreadPool to 
             ' invoke the WaitThreadFunc.
             If count = 2 Then
                ev.Set()
             End If 
             Thread.Sleep(1000)
          Next count
       End Sub 'Main
       
       
       Public Shared Sub ThreadFunc(O As Object)
          
          Console.WriteLine("ThreadPool: WorkItem number: {0}, Values: {1}, {2}", O, A, S)
          
          SyncLock S
             S = "Replacement string"
          End SyncLock
          Console.WriteLine("ThreadPool done. {0}", S)
       End Sub 'ThreadFunc
       
       Public Shared Sub WaitThreadFunc(O As Object, signaled As Boolean)
          If Not (O Is Nothing) Then
             Console.WriteLine("****ThreadPool: WaitWorkItem Type: {0}, Values: {1}", O.GetType().Name, S)
          Else
             Console.WriteLine("****ThreadPool: WaitWorkItem value is: {0}", S)
          End If 
          SyncLock S
             S = "WaitOrTimer: Special timerstring."
          End SyncLock
          ' Demonstrates use of Interlocked to show locking on an Int32.
          Interlocked.Increment(A)
       End Sub 'WaitThreadFunc
    End Class 'Sensor
    [C#]
    using System;
    using System.Threading;public class Sensor 
    {
       static int A = 32;
       static String S = "Initial string";
       
       public static int Main(string[] args){      AutoResetEvent ev = new AutoResetEvent(false);
          ThreadPool.RegisterWaitForSingleObject(
             ev,
             new WaitOrTimerCallback(WaitThreadFunc),
             null,
             20000,
             false
          );      for(int count = 0; count < 5; ++count){
             Console.WriteLine("Hello everyone!!");
             Console.WriteLine("{0}, {1}", A, S);         ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadFunc), 5);
             ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadFunc), 6);         // Signal the AutoResetEvent, which raises the ThreadPool to 
             // invoke the WaitThreadFunc.
             if (count == 2)
                ev.Set();         Thread.Sleep(1000);
          }
          return 0;
       }
       
       public static void ThreadFunc(Object O){      Console.WriteLine("ThreadPool: WorkItem number: {0}, Values: {1}, {2}", O, A, S);      lock(S){
             S = "Replacement string";
          }
          Console.WriteLine("ThreadPool done. {0}", S);
       }   public static void WaitThreadFunc(object O, bool signaled){
          if (O != null){
             Console.WriteLine("****ThreadPool: WaitWorkItem Type: {0}, Values: {1}", O.GetType().Name, S);
          }
          else
             Console.WriteLine("****ThreadPool: WaitWorkItem value is: {0}", S);      lock(S)
          {
             S = "WaitOrTimer: Special timerstring.";
          }
          // Demonstrates use of Interlocked to show locking on an Int32.
          Interlocked.Increment(ref A);
       }
    }
    请参见
    线程处理对象和功能 | ThreadPool 类 | 线程与线程处理 | I/O 异步完成 | Timer--------------------------------------------------------------------------------将文档反馈发送给 Microsoft&copy; 2002 Microsoft Corporation。保留所有权利。
      

  4.   

    .NET 框架类库   ThreadPool 类  [C#]请参见
    ThreadPool 成员 | System.Threading 命名空间 
    要求
    命名空间: System.Threading平台: Windows 98, Windows NT 4.0, Windows Millennium Edition, Windows 2000, Windows XP Home Edition, Windows XP Professional, Windows .NET Server family程序集: Mscorlib (在 Mscorlib.dll 中)
    语言
    C#C++JScriptVisual Basic全部显示
    提供一个线程池,该线程池可用于发送工作项、处理异步 I/O、代表其他线程等待以及处理计时器。有关此类型所有成员的列表,请参阅 ThreadPool 成员。System.Object
       System.Threading.ThreadPool[Visual Basic]
    NotInheritable Public Class ThreadPool
    [C#]
    public sealed class ThreadPool
    [C++]
    public __gc __sealed class ThreadPool
    [JScript]
    public class ThreadPool
    线程安全
    此类型的所有公共静态(Visual Basic 中为 Shared)成员对多线程操作而言都是安全的。但不保证任何实例成员是线程安全的。备注
    许多应用程序创建的线程都要在休眠状态中消耗大量时间,以等待事件发生。其他线程可能进入休眠状态,只被定期唤醒以轮询更改或更新状态信息。线程池通过为应用程序提供一个由系统管理的辅助线程池使您可以更为有效地使用线程。一个线程监视排到线程池的若干个等待操作的状态。当一个等待操作完成时,线程池中的一个辅助线程就会执行对应的回调函数。也可以将与等待操作不相关的工作项排列到线程池。若要请求由线程池中的一个线程来处理工作项,请调用 QueueUserWorkItem 方法。此方法将对将被从线程池中选定的线程调用的方法或委托的引用用作参数。一个工作项排入队列后就无法再取消它。计时器队列中的计时器以及已注册的等待操作也使用线程池。它们的回调函数也会排列到线程池。线程池在首次创建 ThreadPool 类的实例时被创建。线程池具有每个可用处理器 25 个线程的默认限制,这可以使用 mscoree.h 文件中定义的 CorSetMaxThreads 来更改。每个线程使用默认的堆栈大小并按照默认的优先级运行。每个进程只能具有一个操作系统线程池。要求
    命名空间: System.Threading平台: Windows 98, Windows NT 4.0, Windows Millennium Edition, Windows 2000, Windows XP Home Edition, Windows XP Professional, Windows .NET Server family程序集: Mscorlib (在 Mscorlib.dll 中)请参见
    ThreadPool 成员 | System.Threading 命名空间 --------------------------------------------------------------------------------将文档反馈发送给 Microsoft&copy; 2002 Microsoft Corporation。保留所有权利。
      

  5.   

    .NET 框架开发者指南   线程与线程处理请参见
    托管线程处理支持 | 线程池 | ThreadPool
    操作系统使用进程将它们正在执行的不同应用程序分开。线程是操作系统分配处理器时间的基本单元,并且该进程中可以有多个线程同时执行代码。每个线程都维护异常处理程序、调度优先级和一组系统用于在调度该线程前保存线程上下文的结构。线程上下文包括为使线程在线程的宿主进程地址空间中无缝地继续执行所需的所有信息,包括线程的 CPU 寄存器组和堆栈。.NET 框架将操作系统进程进一步细分为由 System.AppDomain 表示的称为应用程序域的轻量托管子进程。一个或多个托管线程(由 System.Threading.Thread 表示)可以在同一个非托管进程中的一个或任意数目的应用程序域中运行。虽然每个应用程序域都是用单个线程启动的,但该应用程序域中的代码可以创建附加应用程序域和附加线程。其结果是托管线程可以在同一个非托管进程中的应用程序域之间自由移动;您可能只使一个线程在若干应用程序域之间移动。支持抢先多任务处理的操作系统可以创建多个进程中的多个线程同时执行的效果。它通过以下方式实现这一点:在需要处理器时间的线程之间分割可用处理器时间,并轮流为每个线程分配处理器时间片。当前执行的线程在其时间片结束时被挂起,而另一个线程继续运行。当系统从一个线程切换到另一个线程时,它将保存被抢先的线程的线程上下文,并重新加载线程队列中下一个线程的已保存线程上下文。时间片的长度取决于操作系统和处理器。由于每个时间片都很小,因此即使只有一个处理器,多个线程看起来似乎是在同时执行。这实际上就是多处理器系统中发生的情形,在此类系统中,可执行线程分布在多个可用处理器中。何时使用多个线程
    需要用户交互的软件必须尽可能快地对用户的活动作出反应,以便提供丰富多彩的用户体验。但同时它必须执行必要的计算以便尽可能快地将数据呈现给用户。如果应用程序仅使用一个执行线程,则可以结合使用异步编程与 .NET 远程处理或使用 ASP.NET 创建的 XML Web services,以便在使用自己计算机的处理时间以外再使用其他计算机的处理时间,从而提高对用户的响应速度并减少应用程序的数据处理时间。如果您正在进行大量的输入/输出工作,则还可以使用 I/O 完成端口来提高应用程序的响应速度。多个线程的优点
    无论如何,要提高对用户的响应速度并且处理所需数据以便几乎同时完成工作,使用多个线程是一种最为强大的技术。在具有一个处理器的计算机上,多个线程可以通过利用用户事件之间很小的时间段在后台处理数据来达到这种效果。例如,在另一个线程正在重新计算同一应用程序中的电子表格的其他部分时,用户可以编辑该电子表格。无需修改,同一个应用程序在具有多个处理器的计算机上运行时将极大地满足用户的需要。单个应用程序域可以使用多个线程来完成以下任务: 通过网络与 Web 服务器和数据库进行通讯。 
    执行占用大量时间的操作。 
    区分具有不同优先级的任务。例如,高优先级线程管理时间关键的任务,低优先级线程执行其他任务。 
    使用户界面可以在将时间分配给后台任务时仍能快速作出响应。 
    多个线程的缺点
    建议您使用尽可能少的线程,这样可以使操作系统资源的使用率最低,并可提高性能。线程处理还具有在设计应用程序时要考虑的资源要求和潜在冲突。这些资源要求如下所述: 系统将为进程、AppDomain 对象和线程所需的上下文信息使用内存。因此,可以创建的进程、AppDomain 对象和线程的数目会受到可用内存的限制。 
    跟踪大量的线程将占用大量的处理器时间。如果线程过多,则其中大多数线程都不会产生明显的进度。如果大多数当前线程处于一个进程中,则其他进程中的线程的调度频率就会很低。 
    使用许多线程控制代码执行非常复杂,并可能产生许多错误。 
    销毁线程需要了解可能发生的问题并对那些问题进行处理。 
    提供对资源的共享访问会造成冲突。为了避免冲突,必须对共享资源的访问进行同步或控制。未能正确地使访问同步(在相同或不同的应用程序域中)会导致诸如死锁(两个线程都停止响应,并且都在等待对方完成)和争用条件(由于意外地出现对两个事件的执行时间的临界依赖性而发生反常的结果)等问题。系统提供了可用于协调多个线程之间的资源共享的同步对象。减少线程的数目使同步资源更为容易。需要同步的资源包括: 系统资源(如通讯端口)。 
    多个进程所共享的资源(如文件句柄)。 
    由多个线程访问的单个应用程序域的资源(如全局、静态和实例字段)。 
    线程处理与应用程序设计
    一般情况下,要为不会阻塞其他线程的相对较短的任务处理多个线程并且不需要对这些任务执行任何特定调度时,使用 ThreadPool 类是一种最简单的方式。但是,有多个理由创建您自己的线程: 如果您需要使一个任务具有特定的优先级。 
    如果您具有可能会长时间运行(并因此阻塞其他任务)的任务。 
    如果您需要将线程放置到单线程单元中(所有 ThreadPool 线程均处于多线程单元中)。 
    如果您需要与该线程关联的稳定标识。例如,您应使用一个专用线程来中止该线程、将其挂起或按名称发现它。 
    请参见
    托管线程处理支持 | 线程池 | ThreadPool
      

  6.   

    恕我愚昧了,还是不是很清楚
    1。使用线程池的好处在哪里?相对于不使用线程池的多线程?是不是减去了线程的创建工作?除此之外呢?性能上是否有好处?
    2。“许多应用程序使用多个线程,但这些线程经常在休眠状态中耗费大量的时间来等待事件发生。其他线程可能进入休眠状态,并且仅定期被唤醒以轮询更改或更新状态信息,然后再次进入休眠状态。使用线程池就可以为应用程序提供一个由系统管理的辅助线程池,从而使您可以集中精力于应用程序任务而不是线程管理。“使用线程池的休眠和我手动休眠区别在哪里?性能?减少编码?
    3。“异步调用、System.Net 套接字连接、异步 I/O 完成以及计时器与注册的等待操作等等。“这些是否必须要通过线程池,我刚学C#,还没看这里。
    4。线程池是否对系统资源如文件或者需要同步的变量等的多个线程调用提供了自动的同步功能。
    5。QueueUserWorkItem是针对一些非休眠的调用,使用线程池的理由又在哪里?我msdn可能不全。不知还有哪个地址有说明?或者帮我贴一下,谢谢。
    我可能比较对一些问题钻牛角尖,请大家别嫌烦,多多指点。