You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

AsyncLock.cs 1.6 kB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. namespace LLama.Web.Async
  2. {
  3. /// <summary>
  4. /// Create an Async locking using statment
  5. /// </summary>
  6. public sealed class AsyncLock
  7. {
  8. private readonly SemaphoreSlim _semaphore;
  9. private readonly Task<IDisposable> _releaser;
  10. /// <summary>
  11. /// Initializes a new instance of the <see cref="AsyncLock"/> class.
  12. /// </summary>
  13. public AsyncLock()
  14. {
  15. _semaphore = new SemaphoreSlim(1, 1);
  16. _releaser = Task.FromResult((IDisposable)new Releaser(this));
  17. }
  18. /// <summary>
  19. /// Locks the using statement asynchronously.
  20. /// </summary>
  21. /// <returns></returns>
  22. public Task<IDisposable> LockAsync()
  23. {
  24. var wait = _semaphore.WaitAsync();
  25. if (wait.IsCompleted)
  26. return _releaser;
  27. return wait.ContinueWith((_, state) => (IDisposable)state, _releaser.Result, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
  28. }
  29. /// <summary>
  30. /// IDisposable wrapper class to release the lock on dispose
  31. /// </summary>
  32. /// <seealso cref="IDisposable" />
  33. private sealed class Releaser : IDisposable
  34. {
  35. private readonly AsyncLock _lockToRelease;
  36. internal Releaser(AsyncLock lockToRelease)
  37. {
  38. _lockToRelease = lockToRelease;
  39. }
  40. public void Dispose()
  41. {
  42. _lockToRelease._semaphore.Release();
  43. }
  44. }
  45. }
  46. }