Skip to content

How to use AsyncNonKeyedLocker

Mark Cilia Vincenti edited this page Apr 21, 2024 · 7 revisions

Using AsyncNonKeyedLocker is straightforward. Usually you'd create an instance of AsyncNonKeyedLocker as a class member. If your class is not a singleton and you need to lock even against other instances of your class, then make sure you set it as static.

Example usage:

using AsyncKeyedLock;

namespace MyNamespace
{
   class MyClass
   {
      private static AsyncNonKeyedLocker _myLock = new AsyncNonKeyedLocker(maxCount: 1);

      public async Task DoSomething(CancellationToken cancellationToken)
      {
         using (_myLock.LockAsync(cancellationToken))
         {
            ...
         }
      }

      public void DoSomethingElseSynchronously()
      {
         using (_myLock.Lock())
         {
            ...
         }
      }
   }
}

There are two methods with a number of overloads: LockAsync, which is an asynchronous method, and Lock which is a synchronous method. They allow for optional passing on of a CancellationToken, a timeout in milliseconds and a timeout setting through a TimeSpan. Internally this uses a SemaphoreSlim so for help with this parameters take a look at the overloaded methods for WaitAsync in Microsoft's documentation for SemaphoreSlim.

Conditional locking

There are also overloaded methods called ConditionalLock and ConditionalLockAsync that accept a boolean parameter which, when set to false, will not do any locking. This can be useful either if you have a setting for enabling/disabling locking, or if you are using recursion given that the locks are not inherently reentrant.

double factorial = Factorial(number);

public static double Factorial(int number, bool isFirst = true)
{
  using (await _myLock.ConditionalLockAsync(isFirst))
  {
    if (number == 0)
      return 1;
    return number * Factorial(number-1, false);
  }
}