System.Threading.ThreadPool vs Semaphore?

时间:2011-12-11 00:01:56

标签: c# multithreading threadpool semaphore

示例线程池:

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这样的现有线程)。这是正确的还是更多,使用信号量是否有任何真正的优势,如果你只是想要一个简单的线程池,但速度和性能是一个问题?

2 个答案:

答案 0 :(得分:6)

您正在比较苹果和奶牛。

ThreadPool支持将Threads用于小任务。它没有任何方便的rendez-vous机制(你的Sleep(1000)是解决这个问题的一个弱解决方案)。

信号量是一种同步线程的方法,它们可以是ThreadPool线程。

答案 1 :(得分:1)

仅当您希望这些线程长时间运行时才创建和管理显式线程,或者您需要尽快将该线程执行。即便如此,您最好还是使用任务并行库并将任务标记为长时间运行。

线程池维护一个空闲的“实时”线程池。因此,当您致电QueueUserWorkItem时,很可能会有一个空闲的线程可以抓住您的工作并继续前进。这并不总是正确的,但通常是这样。当您创建新线程(即var t = new Thread(...))时,总是一些启动开销。

此外,线程池允许您设置池线程的最大数量,并管理工作负载。因此,如果您允许四个池线程并排队十个工作项,则线程池将确保一次只运行四个池线程。在某些方面,您可以将其视为一个隐含的信号量,因为它不会让这四个线程一次运行。但它允许您根据需要排队(在一些大的系统定义的限制内)。