Are these calls blocking or async?

171 views Asked by At

Are executions of methodX() in these two snippets different?

SemaphoreSlim _locker, .Wait(), and WaitAsync() are examples of the same method having either a synchronous and asynchronous version:

A:

SemaphoreSlim _locker = new SemaphoreSlim(1);
async Task methodX()
{
   _locker.Wait();
   // .. rest of the code
}

B:

SemaphoreSlim _locker = new SemaphoreSlim(1);
async Task methodX()
{
   await _locker.WaitAsync();
   // .. rest of the code
}
2

There are 2 answers

0
Marc Gravell On BEST ANSWER

The interesting question is what happens if we can't acquire the lock immediately?

With the first code-sample, the current thread will block, and will become unblocked to continue when the lock becomes acquired, continuing without a thread transition.

With the second code-sample, the await will detect the incomplete state, and use a state machine to attach a continuation to happen when the operation completes, and then unroll itself. Assuming that unroll gets to whatever is driving the threads (usually the thread pool), that thread can then be reused to do other CPU work. At some future point, the continuation will be triggered and the work will reactivate, quite possibly on a different thread (sync-context might mean that the same thread gets used, in particular in UI environments like WinForms).

This continuation machinery has some (small) overheads - nothing comes for free, but it means that you shouldn't run out of threads; as such await is incredibly useful to prevent all your threads on a high-concurrency server being idle, waiting on things like IO, lock acquisition, etc - so that some useful work can still be done.

4
ErroneousFatality On

Both will logically do the same thing. Looking only at that process, both will block its execution on the wait instruction. The difference is that the async version will allow other processes to use your computational resources while you're waiting, while the sync version will just use your computational resources to wait.

In most cases it's better to use the async version when you can.