Using await SemaphoreSlim.WaitAsync in .NET 4

semaphoreslim vs lock
taskcompletionsource
c# async mutex

My application is using .NET 4. I am using await async using nuget package

In my application I want to do an await on sempahore WaitAsync call as follows.

SemaphoreSlim semphore = new SemaphoreSlim(100);
await semphore.WaitAsync();

However I am getting following compilation error.

'System.Threading.SemaphoreSlim' does not contain a definition for 'WaitAsync' and no extension method 'WaitAsync' accepting a first argument of type 'System.Threading.SemaphoreSlim' could be found (are you missing a using directive or an assembly reference?)

Could there be anyway of uisng WaitAsync in .NET 4.0?

You can't use SemaphoreSlim.WaitAsync in .Net 4.0 since this method was added to SemaphoreSlim in .Net 4.5.

You can however implement your own AsyncSemaphore following Stephen Toub's example in Building Async Coordination Primitives, Part 5: AsyncSemaphore:

public class AsyncSemaphore
{
    private readonly static Task s_completed = Task.FromResult(true);
    private readonly Queue<TaskCompletionSource<bool>> m_waiters = new Queue<TaskCompletionSource<bool>>();
    private int m_currentCount; 

    public AsyncSemaphore(int initialCount)
    {
        if (initialCount < 0) throw new ArgumentOutOfRangeException("initialCount");
        m_currentCount = initialCount;
    }

    public Task WaitAsync()
    {
        lock (m_waiters)
        {
            if (m_currentCount > 0)
            {
                --m_currentCount;
                return s_completed;
            }
            else
            {
                var waiter = new TaskCompletionSource<bool>();
                m_waiters.Enqueue(waiter);
                return waiter.Task;
            }
        }
    }
    public void Release()
    {
        TaskCompletionSource<bool> toRelease = null;
        lock (m_waiters)
        {
            if (m_waiters.Count > 0)
                toRelease = m_waiters.Dequeue();
            else
                ++m_currentCount;
        }
        if (toRelease != null)
            toRelease.SetResult(true);
    }
}

c# - Using await SemaphoreSlim.WaitAsync in .NET 4, NET 4. I am using await async using nuget package. In my application I want to do an await on sempahore WaitAsync call as follows. SemaphoreSlim semphore​  Asynchronously waits to enter the SemaphoreSlim, using a 32-bit signed integer to measure the time interval, while observing a CancellationToken. WaitAsync() Asynchronously waits to enter the SemaphoreSlim. WaitAsync(Int32) Asynchronously waits to enter the SemaphoreSlim, using a 32-bit signed integer to measure the time interval.

As others have mentioned, .NET 4.5 introduced SemaphoreSlim.WaitAsync.

For .NET 4.0, you can either write your own async-compatible lock or use one from my Nito.AsyncEx NuGet package.

Async Waiting inside C# Locks, In this post we discover how to replace a lock with a Mutex. from making mistakes; awaiting inside a lock is a recipe for producing deadlocks. NET Semaphore and SemaphoreSlim WaitAsync(); try { await Task. Blocks the current thread until it can enter the SemaphoreSlim, using a TimeSpan that specifies the timeout, while observing a CancellationToken. WaitAsync() Asynchronously waits to enter the SemaphoreSlim. WaitAsync(CancellationToken) Asynchronously waits to enter the SemaphoreSlim, while observing a CancellationToken. WaitAsync(Int32)

WaitAsync is introduced with .Net 4.5. You either need to implement yourself as an extension method by looking into source(not sure if that is possible), or you can use StephenToub's AsyncSemaphore.

SemaphoreSlim.WaitAsync Method (System.Threading), Asynchronously waits to enter the SemaphoreSlim, using a TimeSpan to measure the time interval. The number of milliseconds to wait, Infinite (-1) to wait indefinitely, or zero to test the state of the wait NET Core. 3.1 3.0 2.2 2.1 2.0 1.1 1.0  An await expression cannot occur in the body of a synchronous function, in a query expression, in the block of a lock statement, or in an unsafe context. Since the introduction of C# 5, async / await is used pretty much everywhere.

The class AysncSemaphore, posted in two other answers, does not compile with Framework 4.0, because Task.FromResult is not defined.

This is my alternative version:

public class AsyncSemaphore
{
    private readonly static Task s_completed ;
    private readonly Queue<TaskCompletionSource<bool>> m_waiters = new Queue<TaskCompletionSource<bool>>();
    private int m_currentCount; 

    static AsyncSemaphore()
    {
      var tcs = new TaskCompletionSource<bool>();
      tcs.SetResult(true);
      s_completed = tcs.Task ;
    }

    public AsyncSemaphore(int initialCount)
    {
        if (initialCount < 0) throw new ArgumentOutOfRangeException("initialCount");
        m_currentCount = initialCount;
    }

    public Task WaitAsync()
    {
        lock (m_waiters)
        {
            if (m_currentCount > 0)
            {
                --m_currentCount;
                return s_completed;
            }
            else
            {
                var waiter = new TaskCompletionSource<bool>();
                m_waiters.Enqueue(waiter);
                return waiter.Task;
            }
        }
    }
    public void Release()
    {
        TaskCompletionSource<bool> toRelease = null;
        lock (m_waiters)
        {
            if (m_waiters.Count > 0)
                toRelease = m_waiters.Dequeue();
            else
                ++m_currentCount;
        }
        if (toRelease != null)
            toRelease.SetResult(true);
    }
}

SemaphoreSlim Class (System.Threading), The example starts five tasks, all of which block waiting for the semaphore. It is the programmer's responsibility to ensure that calls to Wait or WaitAsync methods are appropriately paired with calls to NET Core. 3.1 3.0 2.2 2.1 2.0 1.1 1.0  Calling WaitAsync on the semaphore produces a task that will be completed when that thread has been given "access" to that token. await -ing that task lets the program continue execution when it is "allowed" to do so.

No, you'll need to upgrade to .NET 4.5 (or write a WaitAsync extension (or inherently asynchronous semaphore) yourself).

The async extensions for .NET 4.0 are there to allow for the support of the actual await keyword. Much of the work of .NET 4.5 is adding asynchronous operations to various BCL types that can be awaited. If you need those operations, you'll need to upgrade the version of the framework you use.

Awaiting in C# lock block?, We will take advantage of SemaphoreSlim class that was introduced in .NET Framework 4.0 in System.Threading namespace. If we think about  The SemaphoreSlim class was updated on.NET 4.5 (and Windows Phone 8) to support async waits. You would have to build your own IDisposable Release, though. (In the situation you describe, I usually just disable the button at the beginning of the async handler and re-enable it at the end; but async synchronization would work too).

SemaphoreSlim's WaitAsync puzzle, NET, C#, Multithreading/Parallelism/Asynchronous/Concurrency static async Task Process(SemaphoreSlim sem, int x) { await sem. the machinery with continuations); I'll “compute” for 500ms; I'll “non-blockingly wait” for  C# (CSharp) System.Threading SemaphoreSlim.WaitAsync - 30 examples found. These are the top rated real world C# (CSharp) examples of System.Threading.SemaphoreSlim.WaitAsync extracted from open source projects. You can rate examples to help us improve the quality of examples.

c# - esperan SemaphoreSlim.WaitAsync en .NET 4, Net 4.0 ya que este método se ha agregado a SemaphoreSlim en . de Stephen Toub en Building Async Coordination Primitives, Part 5: AsyncSemaphore: NET 4.0, puede write your own async-compatible lock o use one desde mi Nito. The other reason is that during an await while holding a lock, arbitrary code may execute while the lock is held. For this reason, the compiler goes out of its way to disallow await expressions within lock blocks. You can still shoot yourself in the foot by using Monitor or other primitives directly, though.

C# locks and async Tasks., Using await SemaphoreSlim.WaitAsync in .NET 4. My application is using .NET 4​. I am using await async using nuget package In my application I want to do an  Within an async method, you can't use the await operator in the body of a synchronous function, inside the block of a lock statement, and in an unsafe context. The operand of the await operator is usually of one of the following .NET types: Task, Task<TResult>, ValueTask, or ValueTask<TResult>.

Comments
  • This doesn't compile with Framework 4.0 because Task.FromResult is not defined. I have replaced Task.FromResult(true) with new TaskCompletionSource<bool>(true).Task. This compiles but I haven't tested it yet.
  • My simple change did not work. I have made a different change and posted the code as a separate answer.
  • you first link is dead and the seconf one pointing to GitHub AsyncEx doesn't support anymore .Net 4.0.
  • @sodjsn26fr: Microsoft changed the first link, and if you still need .NET 4.0 in 2020, you'll need to use an old version of Nito.AsyncEx which is still available on NuGet.
  • @Phil Jollans, thank you. But I tried "Phil Jollans" answer with success. Regards.
  • It's working for me. Thank you.