Why there is no method for acquiring multiple permits on semaphore in C#? I want to use my semaphore like this:
semaphore.Acquire(2);
Good api design is a fine art, truly mastered only by a few. One important aspect is to emphasize commonality. The .NET Semaphore class has that, you use WaitOne()
to acquire the semaphore. Like you do on all of the synchronization classes.
And it becomes especially a fine art by knowing what to leave out. A custom Aquire(n)
method would be high on that cut list. It is a very troublesome method, the underlying native implementation on Windows doesn't support it either. Which produces the serious risk of inducing deadlock that's next to impossible to debug, the code would be hung inside an invisible method that's looping, buried deep inside the CLR. Which adds lots of semantics to waits that matter a great deal when code needs to be aborted. You're free to loop yourself, a simple workaround and of course well visible when you debug a deadlock, you can at least inspect the counter.
The .Net Semaphore
object is a wrapper around the Win32 Semaphore object. Since the Win32 semaphores don't have any mechanism to acquire multiple resources at once, there is no easy way to provide it in the .Net Framework.
Of course it's possible that Microsoft could have implemented their own abstraction over Win32 semaphores, but then they couldn't be included in a WaitAll
call. It's quite likely that MS never even considered implementing this feature.
You may write your own extention method to Semaphore class:
namespace Extentions
{
public static class SemaphoreExtentions
{
public static void Acquire(this Semaphore semaphore, int permits)
{
for (int i = 0; i < permits; ++i)
semaphore.WaitOne();
}
}
}
Usage:
using Extentions;
//...
public void SomeMethod()
{
var sem = new Semaphore(10, 10);
sem.Acquire(6);
}
Update To avoid deadlocks:
public static void Acquire(this Semaphore semaphore, int permits)
{
lock (semaphore)
{
for (int i = 0; i < permits; ++i)
semaphore.WaitOne();
}
}
Of course you shouldn't lock this semaphore somewhere else because it may cause deadlocks too. Another option is to change signature of the method to Acquire(this Semaphore semaphore, int permits, object sync) and lock sync object.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With