views:

83

answers:

4

We have a situation where we want to limit the number of paralell requests our application can make to its application server. We have potentially 100+ background threads running that will want to at some point make a call to the application server but only want 5 threads to be able to call SendMessage() (or whatever the method will be) at any one time. What is the best way of achieving this?

I have considered using some sort of gatekeeper object that blocks threads coming into the method until the number of threads executing in it has dropped below the threshold. Would this be a reasonable solution or am I overlooking the fact that this might be dirty/dangerous?

We are developing in C#.NET 3.5.

Thanks,

Steve

+9  A: 

Use a semaphore

http://msdn.microsoft.com/en-us/library/system.threading.semaphore.aspx

Limits the number of threads that can access a resource or pool of resources concurrently.

Hasan Khan
+1  A: 

The Semaphore class was designed for exactly this scenario.

Josh Einstein
+3  A: 

You want a semaphore... System.Threading.Semaphore

public static class MyClass
{
    private static Semaphore sem = new Semaphore(5, 5);

    public static void SendMessage()
    {
        sem.WaitOne();

        try
        {
        }
        finally
        {
            sem.Release(1);
        }
    }
}

Alternatively, if you only want a single thread to be able to call a method at a given time, .NET also exposes a concept equivalent with java's synchronized attribute:

[System.Runtime.CompilerServices.MethodImpl(MethodImpl.Synchronized)]
LorenVS
you probably want to release the semaphore even if an exception *isn't* thrown. Put it in the finally block
Isak Savo
oops, my bad, thanks
LorenVS
The method-level synchronization attribute is bad. It locks on "this" for instance members and even worse, the type for static members. It should never be used.
Josh Einstein
Its there, its quick, its painless... Saying it should never be used is a little overkill... I agree there are better solutions, but it is provided
LorenVS
+1  A: 

Design Pattern Approach: - Use command pattern with five Executor threads and wrap your requests in Command classes.

baris_a