Does SemaphoreSlim (.NET) prevent same thread from entering block?

From the documentation:

The SemaphoreSlim class doesn’t enforce thread or task identity on calls to the Wait, WaitAsync, and Release methods

In other words, the class doesn’t look to see which thread is calling it. It’s just a simple counter. The same thread can acquire the semaphore multiple times, and that will be the same as if multiple threads acquired the semaphore. If the thread count remaining is down to 0, then even if a thread already was one that had acquired the semaphore that thread, if it calls Wait(), it will block until some other thread releases the semaphore.

So, with respect to async/await, the fact that an await may or may not resume in the same thread where it was started doesn’t matter. As long as you keep your Wait() and Release() calls balanced, it will work as one would hope and expect.

In your example, you’re even waiting on the semaphore asynchronously, and thus not blocking any thread. Which is good, because otherwise you’d deadlock the UI thread the second time you pressed your button.

Related reading:
Resource locking between iterations of the main thread (Async/Await)
Why does this code not end in a deadlock
Locking with nested async calls

Note in particular caveats on re-entrant/recursive locking, especially with async/await. Thread synchronization is tricky enough as it is, and that difficulty is what async/await is designed to simplify. And it does so significantly in most cases. But not when you mix it with yet another synchronization/locking mechanism.

Leave a Comment