.NET多线程同步方法详解(七):线程池(Thread Pooling)

来源:互联网 发布:辐照食品 知乎 编辑:程序博客网 时间:2024/05/21 09:23

    如果你的应用程序拥有大量的线程并花费大量的时间阻塞在一个Wait Handle上,那么你要考虑使用线程池(Thead pooling)来处理。线程池通过合并多个Wait Handle来节约等待的时间。当Wait Handle被激活时,使用线程池你需要注册一个Wait Handle到一个委托去执行。通过调用ThreadPool.RegisterWaitForSingleObject方法:

    class Test 
    {
        
static ManualResetEvent starter = new ManualResetEvent(false); 
        
public static void Main()
        {
            ThreadPool.RegisterWaitForSingleObject(starter, Go, 
"hello"-1true);
            Thread.Sleep(
5000);
            Console.WriteLine(
"Signaling worker...");
            starter.Set(); 
            Console.ReadLine();
        }
        
public static void Go(object data, bool timedOut) 
        {
            Console.WriteLine(
"Started " + data); // Perform task... 
        }
    } 

    对于Wait Handle和委托,RegisterWaitForSingleObject接受一个"黑盒"对象并传递给你的委托(就像ParameterizedThreadStart),超时设置和boolean标志指示了关闭和循环的请求。所有进入池中的线程都被认为是后台线程,这就意味着它们不再由应用程序控制,而是由系统控制直到应用程序退出。

    注意:如果这时候调用Abort操作,可能会发生意想不到的情况。
  
   你也可以通过调用QueueUserWorkItem方法使用线程池,指定委托并立即被执行。这时你不能在多任务情况下保存共享线程,但是可以得到另外的好处:线程池会保持一个线程的总容量,当作业数超出容量时自动插入任务。

 

    class Test 
    {
        
static object workerLocker = new object();
        
static int runningWorkers = 100;
        
public static void Main() 
        {
            
for (int i = 0; i < runningWorkers; i++
            {
                ThreadPool.QueueUserWorkItem(Go, i); 
            }
            Console.WriteLine(
"Waiting for threads to complete..."); 
            
lock (workerLocker) 
            {
                
while (runningWorkers > 0
                    Monitor.Wait(workerLocker);
            }
            Console.WriteLine(
"Complete!");
            Console.ReadLine(); 
        }
        
public static void Go(object instance) 
        {
            Console.WriteLine(
"Started: " + instance);
            Thread.Sleep(
1000); 
            Console.WriteLine(
"Ended: " + instance); 
            
lock (workerLocker)
            {
                runningWorkers
--;
                Monitor.Pulse(workerLocker);
            }
        }
    } 

  为了传递多个对象到目标方法,你必须定义一个客户对象并包含所有属性或通过调用异步的委托。如Go方法接受两参数:

ThreadPool.QueueUserWorkItem (delegate (object notUsed) { Go (23,34); }); 

 其他的方法可以使用异步委托。

 

原创粉丝点击