Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A function that only permits N concurrent threads

I have a Visual Studio 2008 C# .NET 3.5 project where a class listens for an event invocation from another class that is multithreaded. I need to ensure that my event only allows simultaneous access to a maximum of 10 threads. The 11th thread should block until one of the 10 finishes.

myobj.SomeEvent += OnSomeEvent;

private void OnSomeEvent(object sender, MyEventArgs args)
{
    // allow up to 10 threads simultaneous access. Block the 11th thread.
    using (SomeThreadLock lock = new SomeThreadLock(10))
    {         
        DoUsefulThings(args.foo);
    }
}

I do not have control over the other MyObj class, so I cannot implement a threadpool there.

What is the best way to implement this?

Thanks, PaulH

like image 231
PaulH Avatar asked Apr 16 '12 15:04

PaulH


3 Answers

You want the Semaphore class. It is, in short, a lock that only allows a specified number of callers through at any time.

Since you don't control the creation of threads, you do need to be careful about deadlock situations. Semaphores are not reentrancy-aware- if a given thread enters a semaphore more than once, it will take more than one slot. So if each of your caller's threads enters your semaphore more than once, there is the possibility of a deadlock.

like image 113
Chris Shain Avatar answered Nov 12 '22 13:11

Chris Shain


Use a Semaphore for this. The constructor parameters are a little confusing to those just getting introduced to the class. The first parameter specifies the initial number of threads allowed through right now. The second parameter specifies the maximum number of threads allowed through at any given time.

myobj.SomeEvent += OnSomeEvent;
Semaphore semaphore = new Semaphore(10, 10);

private void OnSomeEvent(object sender, MyEventArgs args)
{
  semaphore.WaitOne();
  try
  {
    DoUsefulThings(args.foo);
  }
  finally
  {
    semaphore.Release();
  }
}
like image 41
Brian Gideon Avatar answered Nov 12 '22 15:11

Brian Gideon


It's customary to use a semaphore for this. Initialize it to 10 units. wait() for one unit before DoUsefulThings(), signal() one unit afterwards.

like image 3
Martin James Avatar answered Nov 12 '22 13:11

Martin James