Niklas
Niklas

Reputation: 1853

System.Threading.ThreadPool vs Semaphore?

Example threadpool:

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.");
}
}

Example Semaphore:

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());
}
}

I guess its some overhead with the Semaphore, to create 5 threads in this example, but the threadpool, uses the built in "threadpool" (it will use existing threads like the backgroundworker) . Is this correct or is it more to this, is there any real advantage to use a semaphore, if you just want a simple threadpool but speed and performance is an issue?

Upvotes: 1

Views: 4694

Answers (2)

Jim Mischel
Jim Mischel

Reputation: 133995

Create and manage explicit threads only if you expect those threads to be long running, OR you need to have that thread executed as soon as possible. Even then, you're probably better off using the Task Parallel Library and marking the task as long-running.

The thread pool maintains a pool of "live" threads that are idle. So when you call QueueUserWorkItem, it's highly likely that there will be an idle thread that can grab your work and go. That's not always true, but it often is. When you create a new thread (i.e. var t = new Thread(...)), there is always some startup overhead.

In addition, the thread pool lets you set the maximum number of pool threads, and manages the workload. So if you allow four pool threads and queue ten work items, the thread pool will ensure that only four pool threads are running at a time. In some ways, you can think of it as an implicit semaphore in that it won't let more than those four threads run at a time. But it lets you queue as many as you want (within some large system-defined limit).

Upvotes: 1

Henk Holterman
Henk Holterman

Reputation: 273244

You are comparing Apples and Cows.

The ThreadPool enables using Threads for small tasks. It lacks any convenient rendez-vous mechanism (your Sleep(1000) is a weak solution to that problem).

A semaphore is a way to sync-up threads, they could be ThreadPool threads.

Upvotes: 7

Related Questions