示例线程池:
public class Example {
public static void Main() {
ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc)); //task 1
ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc)); //task 2
ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc)); //task 3
Console.WriteLine("Main thread does some work, then sleeps.");
Thread.Sleep(1000);
Console.WriteLine("Main thread exits.");
}
static void ThreadProc(Object stateInfo) {
Console.WriteLine("Hello from the thread pool.");
}
}
示例信号量:
public class Example
{
private static Semaphore _pool;
private static int _padding;
public static void Main()
{
_pool = new Semaphore(0, 3);
// Create and start five numbered threads.
//
for(int i = 1; i <= 5; i++)
{
Thread t = new Thread(new ParameterizedThreadStart(Worker));
t.Start(i);
}
Thread.Sleep(500);
Console.WriteLine("Main thread calls Release(3).");
_pool.Release(3);
Console.WriteLine("Main thread exits.");
}
private static void Worker(object num)
{
Console.WriteLine("Thread {0} begins " +
"and waits for the semaphore.", num);
_pool.WaitOne();
int padding = Interlocked.Add(ref _padding, 100);
Console.WriteLine("Thread {0} enters the semaphore.", num);
Thread.Sleep(1000 + padding);
Console.WriteLine("Thread {0} releases the semaphore.", num);
Console.WriteLine("Thread {0} previous semaphore count: {1}",
num, _pool.Release());
}
}
我猜它是Semaphore的一些开销,在这个例子中创建了5个线程, 但是线程池使用内置的&#34;线程池&#34; (它将使用像backgroundworker这样的现有线程)。这是正确的还是更多,使用信号量是否有任何真正的优势,如果你只是想要一个简单的线程池,但速度和性能是一个问题?
答案 0 :(得分:6)
您正在比较苹果和奶牛。
ThreadPool支持将Threads用于小任务。它没有任何方便的rendez-vous机制(你的Sleep(1000)是解决这个问题的一个弱解决方案)。
信号量是一种同步线程的方法,它们可以是ThreadPool线程。
答案 1 :(得分:1)
仅当您希望这些线程长时间运行时才创建和管理显式线程,或者您需要尽快将该线程执行。即便如此,您最好还是使用任务并行库并将任务标记为长时间运行。
线程池维护一个空闲的“实时”线程池。因此,当您致电QueueUserWorkItem
时,很可能会有一个空闲的线程可以抓住您的工作并继续前进。这并不总是正确的,但通常是这样。当您创建新线程(即var t = new Thread(...)
)时,总是一些启动开销。
此外,线程池允许您设置池线程的最大数量,并管理工作负载。因此,如果您允许四个池线程并排队十个工作项,则线程池将确保一次只运行四个池线程。在某些方面,您可以将其视为一个隐含的信号量,因为它不会让这四个线程一次运行。但它允许您根据需要排队(在一些大的系统定义的限制内)。