A function that only permits N concurrent threads
Asked Answered
H

3

14

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

Hern answered 16/4, 2012 at 15:17 Comment(0)
S
21

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.

Stannary answered 16/4, 2012 at 15:18 Comment(0)
D
9

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();
  }
}
Diane answered 16/4, 2012 at 15:31 Comment(1)
+1 for noting that you should exit the semaphore in the finally block of a try/catch. This is important stuff- in case your code throws an exception, you want to make sure the semaphore is exited.Stannary
H
3

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

Hardaway answered 16/4, 2012 at 15:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.