ThreadPool in .Net

在多线程的程序中,经常会出现两种情况。一种情况下,应用程序中的线程把大部分的时间花费在等待状态,等待某个事件发生,然后才能给予响应;而另外一种情况则是线程平常都处于休眠状态,只是周期性地被唤醒。这里分析及介绍 .Net Framework ThreadPool class 来对付第一种情况,相应地也会谈到 QueueUserWorkItem 方法和 WaitCallback 委托。而使用 Timer System.Threading.Timer or System.Windows.Forms.Timer )来对付第二种情况,可以参考《 System.Threading.Timer类的TimerCallback 委托 》。
 
1. ThreadPool 介绍( From MSDN
ThreadPool class 提供了一个线程池,该线程池可用于发送工作项、处理异步 I/O 、代表其他线程等待以及处理计时器。线程池允许在后台运行多个工作,而不需要为每个任务频繁地创建和销毁单独的线程,从而减少了开销。
 
线程池通过为应用程序提供一个由系统管理的辅助线程池使您可以更为有效地使用线程。一个线程监视排到线程池的若干个等待操作的状态。当一个等待操作完成时,线程池中的一个辅助线程就会执行对应的回调函数。
 
也可以将与等待操作不相关的工作项排列到线程池。若要请求由线程池中的一个线程来处理工作项,请调用 QueueUserWorkItem 方法。此方法将对将被从线程池中选定的线程调用的方法或委托的引用用作参数。一个工作项排入队列后就无法再取消它。
 
计时器( System.Threading.Timer )队列中的计时器以及已注册的等待操作也使用线程池。它们的回调函数也会排列到线程池。关于这部分的内容,可以参考《 System.Threading.Timer类的TimerCallback 委托 》。
 
线程池在首次创建 ThreadPool 类的实例时被创建。线程池具有每个可用处理器 25 个线程的默认限制,这可以使用 mscoree.h 文件中定义的 CorSetMaxThreads 来更改。每个线程使用默认的堆栈大小并按照默认的优先级运行。每个进程只能具有一个操作系统线程池。
 
2. ThreadPool.QueueUserWorkItem 方法
QueueUserWorkItem 方法将指定的方法排入队列以便执行,并指定包含该方法所用数据的对象,此方法在有线程池线程变得可用时执行。
public static bool QueueUserWorkItem(
   WaitCallback callBack,
   object state
);
如果将方法成功排入队列,则为 true ;否则为 false 。如果排入队列的方法仅需要单个数据项,可以将数据项强制转换为类型 Object 。如果该方法需要多个复杂数据,则必须定义包含这些数据的类。如果没有参数传入,则可以调用 QueueUserWorkItem(WaitCallback callBack) 重载。
 
ThreadPool 提供的公共方法都是 static 方法,因此也不需要生成 ThreadPool 对象。通过 QueueUserWorkItem 方法在线程池中添加一个工作项目后,目前没有提供简单的方法取消。你不必建立咨监线程,只需要把相应的函数或方法依托 WaitCallback 委托传递给 ThreadPool.QueueUserWorkItem() 方法即可。而线程的创建、管理和运行等等都由系统自动完成,这就是 ThreadPool 的优点。
 
 
3. WaitCallback 委托
WaitCallback 委托声明线程池要执行的回调方法,回调方法的声明必须与 WaitCallback 委托声明具有相同的参数。
 
WaitCallback 表示要在 ThreadPool 线程上执行的回调方法。创建委托,方法是将回调方法传递给 WaitCallback 构造函数。您的方法必须具有此处所显示的签名。通过将 WaitCallback 委托传递给 ThreadPool.QueueUserWorkItem 来将任务排入队列以便执行。您的回调方法将在某个线程池线程可用时执行。
如果要将信息传递给回调方法,请创建包含所需信息的对象,并在将任务排入队列以便执行时将它传递给 QueueUserWorkItem 。每次执行您的回调方法时, state 参数都包含此对象。
 
通过将一个方法打包到 WaitCallback 委托中,然后将该委托传递给 ThreadPool.QueueUserWorkItem 静态方法,在线程池中对任务进行排队。
 
4. Demo application using ThreadPool class
codeproject.com 上有一个不错的 Demo: Proper Threading in Winforms .Net, written by Shawn Cicoria ,并附有 Source code
 
在上述 Demo 程序中,不仅提供了使用 ThreadPool 线程池的方法,而且还演示了 Thread ThreadStart 委托的方法。
private void button1_Click(object sender, System.EventArgs e)
{
          ShowProgressDelegate showProgress = new ShowProgressDelegate(ShowProgress);
          int imsgs = 100;
 
          //One Way... Using ThreadPool
          if ( cbThreadPool.Checked )
          {
                    object obj = new object[] { this, showProgress, imsgs };
                    WorkerClass wc = new WorkerClass();
                    bool rc = ThreadPool.QueueUserWorkItem( new WaitCallback (wc.RunProcess), obj);
                    EnableButton( ! rc );
          }
          else
          {
                    //another way.. using straight threads
                    WorkerClass wc = new WorkerClass( this, showProgress, new object[] { imsgs } );
                    Thread t = new Thread( new ThreadStart(wc.RunProcess));
                    t.IsBackground = true; //make them a daemon - prevent thread callback issues
                    t.Start();
                    EnableButton ( false );
          }
}
 
另外,上述 Demo 程序中还调用 Windows form 控件的 BeginInvoke 方法:在创建控件的基础句柄所在线程上,用指定的参数异步执行指定委托。 BeginInvoke 方法在不同的线程池线程上回调指定的委托,实际上就是发起后台的调用来放置一条消息到 windows form 的消息循环( message loop )中。
public IAsyncResult BeginInvoke(Delegate, object[]);
 
***
Any questions about the demo application, please leave message below. I will try to explain it. Thanks.
 
 
References:
1, MSDN, ThreadPool, QueueUserWorkItem and WaitCallback
2, Shawn Cicoria, Proper Threading in Winforms .Net, http://www.codeproject.com/csharp/winformthreading.asp
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值