2011-09-29 60 views
4

我知道CLR给每个AppDomainThreadPool时间片工作,但我想,如果通过创建像这样Thread t = new Thread(...);线程是否由线程池管理?

一个新的线程它由CLR或由AppDomin ThreadPool设法知道吗?

回答

3

当您使用Thread类创建线程时,您可以控制。您可以根据需要创建它们,并且您可以定义它们是否为background or foreground(使呼叫进程保持活动状态),您可以设置它们的Priority,然后启动并停止它们。

随着ThreadPoolTask(其中使用ThreadPool幕后)你让ThreadPool类管理线程的创建,并最大限度地提高线程的可重用性,从而节省您创建一个新的线程所需要的时间。需要注意的一点是,与Thread默认值不同,ThreadPool创建的线程不会使调用进程保持活动状态。

使用ThreadPool的一个巨大优势是可以让少量线程处理大量任务。相反,假设池没有杀死线程(因为它是为了重用而设计的),如果你有一堆由ThreadPool创建的线程,但后来项目数量减少,则ThreadPool闲置很多,浪费资源。

6

Thread t = new Thread();将不受ThreadPool的管理。但它是CLR在操作系统线程上提供的一种抽象。 ThreadPool是一个附加的抽象,它有助于重用线程和共享线程资源。

这里是在.NET上线的优秀资源:http://www.albahari.com/threading/

如果你使用.NET 4.0考虑使用第三方物流。

+0

我使用.NET 4.0 在面试时,我说,一个线程不是由线程池管理和组长说我错了。现在的问题是我纠正他:) – guyl

+0

真棒链接,谢谢! –

1

当您创建新线程时,它们是由线程池管理的而不是

1

如果您手动创建线程,那么您可以控制其使用寿命,这与线程池无关。

0

以下示例说明如何使用线程池。它首先创建一个ManualResetEvent对象,该对象使程序能够知道线程池何时完成了所有工作项目的运行。接下来,它试图向线程池添加一个线程。如果成功,则添加其余部分(本例中为四个)。线程池然后将工作项放入可用的线程中。 eventX上的WaitOne方法被调用,这会导致程序的其余部分等待,直到触发事件(使用eventX.Set方法)。最后,程序打印线程上的加载(实际执行特定工作项的线程)。

// SimplePool.cs 
// Simple thread pool example 
using System; 
using System.Collections; 
using System.Threading; 

// Useful way to store info that can be passed as a state on a work item 
public class SomeState 
{ 
    public int Cookie; 
    public SomeState(int iCookie) 
    { 
     Cookie = iCookie; 
    } 
} 

public class Alpha 
{ 
    public Hashtable HashCount; 
    public ManualResetEvent eventX; 
    public static int iCount = 0; 
    public static int iMaxCount = 0; 
    public Alpha(int MaxCount) 
    { 
     HashCount = new Hashtable(MaxCount); 
     iMaxCount = MaxCount; 
    } 

    // Beta is the method that will be called when the work item is 
    // serviced on the thread pool. 
    // That means this method will be called when the thread pool has 
    // an available thread for the work item. 
    public void Beta(Object state) 
    { 
     // Write out the hashcode and cookie for the current thread 
     Console.WriteLine(" {0} {1} :", Thread.CurrentThread.GetHashCode(), 
     ((SomeState)state).Cookie); 
     // The lock keyword allows thread-safe modification 
     // of variables accessible across multiple threads. 
     Console.WriteLine(
     "HashCount.Count=={0}, Thread.CurrentThread.GetHashCode()=={1}", 
     HashCount.Count, 
     Thread.CurrentThread.GetHashCode()); 
     lock (HashCount) 
     { 
     if (!HashCount.ContainsKey(Thread.CurrentThread.GetHashCode())) 
      HashCount.Add (Thread.CurrentThread.GetHashCode(), 0); 
     HashCount[Thread.CurrentThread.GetHashCode()] = 
      ((int)HashCount[Thread.CurrentThread.GetHashCode()])+1; 
     } 

     // Do some busy work. 
     // Note: Depending on the speed of your machine, if you 
     // increase this number, the dispersement of the thread 
     // loads should be wider. 
     int iX = 2000; 
     Thread.Sleep(iX); 
     // The Interlocked.Increment method allows thread-safe modification 
     // of variables accessible across multiple threads. 
     Interlocked.Increment(ref iCount); 
     if (iCount == iMaxCount) 
     { 
     Console.WriteLine(); 
     Console.WriteLine("Setting eventX "); 
     eventX.Set(); 
     } 
    } 
} 

public class SimplePool 
{ 
    public static int Main(string[] args) 
    { 
     Console.WriteLine("Thread Pool Sample:"); 
     bool W2K = false; 
     int MaxCount = 10; // Allow a total of 10 threads in the pool 
     // Mark the event as unsignaled. 
     ManualResetEvent eventX = new ManualResetEvent(false); 
     Console.WriteLine("Queuing {0} items to Thread Pool", MaxCount); 
     Alpha oAlpha = new Alpha(MaxCount); // Create the work items. 
     // Make sure the work items have a reference to the signaling event. 
     oAlpha.eventX = eventX; 
     Console.WriteLine("Queue to Thread Pool 0"); 
     try 
     { 
     // Queue the work items, which has the added effect of checking 
     // which OS is running. 
     ThreadPool.QueueUserWorkItem(new WaitCallback(oAlpha.Beta), 
      new SomeState(0)); 
     W2K = true; 
     } 
     catch (NotSupportedException) 
     { 
     Console.WriteLine("These API's may fail when called on a non-Windows 2000 system."); 
     W2K = false; 
     } 
     if (W2K) // If running on an OS which supports the ThreadPool methods. 
     { 
     for (int iItem=1;iItem < MaxCount;iItem++) 
     { 
      // Queue the work items: 
      Console.WriteLine("Queue to Thread Pool {0}", iItem); 
      ThreadPool.QueueUserWorkItem(new WaitCallback(oAlpha.Beta),new SomeState(iItem)); 
     } 
     Console.WriteLine("Waiting for Thread Pool to drain"); 
     // The call to exventX.WaitOne sets the event to wait until 
     // eventX.Set() occurs. 
     // (See oAlpha.Beta). 
     // Wait until event is fired, meaning eventX.Set() was called: 
     eventX.WaitOne(Timeout.Infinite,true); 
     // The WaitOne won't return until the event has been signaled. 
     Console.WriteLine("Thread Pool has been drained (Event fired)"); 
     Console.WriteLine(); 
     Console.WriteLine("Load across threads"); 
     foreach(object o in oAlpha.HashCount.Keys) 
      Console.WriteLine("{0} {1}", o, oAlpha.HashCount[o]); 
     } 
     return 0; 
    } 
} 

出把

Thread Pool Sample: 
Queuing 10 items to Thread Pool 
Queue to Thread Pool 0 
Queue to Thread Pool 1 
... 
... 
Queue to Thread Pool 9 
Waiting for Thread Pool to drain 
98 0 : 
HashCount.Count==0, Thread.CurrentThread.GetHashCode()==98 
100 1 : 
HashCount.Count==1, Thread.CurrentThread.GetHashCode()==100 
98 2 : 
... 
... 
Setting eventX 
Thread Pool has been drained (Event fired) 

Load across threads 
101 2 
100 3 
98 4 
102 1