线程池ThreadPool的使用

创建线程需要时间。如果有不同的小任务需要完成,就可以事先创建许多线程,在应完成这些任务的时候发出请求。这个线程数最好在需要更多的线程时增加,在需要释放资源时减少。在.NET Framework中不需要自己创建这样一个列表,该列表由ThreadPool类托管。这个类会在需要时增减线程池中的线程数,直到最大的线程数。池中的最大线程数是可以配置的。在双核CPU中,默认设置为1023个工作线程和1000个I/O线程。也可以指定在创建线程池时应立即启动的最小线程数,以及线程池中可用的最大线程数。如果有更多的作业需要处理,线程池中的线程个数达到了极限,最新的作业就要排队,且必须等待线程完成其任务。

来看下面这个示例:

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Text;
   5: using System.Threading;
   6:  
   7: namespace Threadpool
   8: {
   9:     class Program
  10:     {
  11:         static void Main(string[] args)
  12:         {
  13:             //用来保存工作线程的个数
  14:             int nWorkerThreads;
  15:             //用来保存I/O线程的个数
  16:             int nCompletionPortThreads;
  17:               //读取工作线程和I/O线程的最大线程数
  18:             ThreadPool.GetMaxThreads(out nWorkerThreads,out nCompletionPortThreads);
  19:             //把这些信息写入到控制台
  20:             Console.WriteLine("Max worker threads:{0},"+
  21:                               "I/O completion threads:{1}",
  22:                               nWorkerThreads,nCompletionPortThreads);
  23:             //在for循环中,调用ThreadPool.QueueUserWorkItem()方法,传递一个WaitCallback类型的委托,把JobForAThread()方法赋予线程池中的线程
  24:               //线程池收到这个请求后,就会从池中选择一个线程,来调用该方法。如果线程池还没有运行,就会创建一个线程池,并启动第一个线程。如果线程池已经在
  25:               //运行,且有一个空闲线程来完成该任务,就把该作业传递给这个线程。
  26:             for (int i = 0; i < 5;i++)
  27:             {
  28:                 ThreadPool.QueueUserWorkItem(JobForThread);
  29:             }
  30:             Console.ReadKey();
  31:         }
  32:  
  33:         static void JobForThread(object state)
  34:         {
  35:             for(int i=0;i<3;i++)
  36:             {
  37:                 Console.WriteLine("loop {0},running inside pooled thread {1}", i, Thread.CurrentThread.ManagedThreadId);
  38:                 Thread.Sleep(50);
  39:             }
  40:         }
  41:     }
  42: }

运行结果如下所示:

image

由运行结果可以看出5个作用只有线程池中的两个线程处理。读者运行该程序的结果可能与此不同,也可以改变作业的睡眠时间和要处理的作业数,得到完全不同的结果。

线程池使用起来很简单,但是它有一些限制:

1)、线程池中的所有线程都是后台线程。如果进程的所有前台线程都结束了,所有的后台线程就会停止。不能把入池的线程改为前台线程。

2)、不能给入池的线程设置优先级或名称。

3)、对于COM对象,入池的所有线程都是多线程单元(multithreaded apartment,MTA)线程。许多COM对象都需要单线程单元(single-threaded apartment,MTA)线程。

4)、入池的线程只能用于时间较短的任务。如果线程要一直运行(如word的拼写检查器线程),就应该使用

Thread类创建一个线程。

posted @ 2012-09-11 10:39  美梦成真  阅读(1129)  评论(0编辑  收藏  举报