4
4
5
5
namespace NHibernate . Util
6
6
{
7
- public class AsyncLock
7
+ // Source from https://www.hanselman.com/blog/ComparingTwoTechniquesInNETAsynchronousCoordinationPrimitives.aspx
8
+ public sealed class AsyncLock
8
9
{
9
- private readonly AsyncSemaphore semaphore ;
10
- private readonly Task < Releaser > releaser ;
10
+ private readonly SemaphoreSlim _semaphore = new SemaphoreSlim ( 1 , 1 ) ;
11
+ private readonly Task < IDisposable > _releaser ;
11
12
12
13
public AsyncLock ( )
13
14
{
14
- semaphore = new AsyncSemaphore ( 1 ) ;
15
- releaser = Task . FromResult ( new Releaser ( this ) ) ;
15
+ _releaser = Task . FromResult ( ( IDisposable ) new Releaser ( this ) ) ;
16
16
}
17
17
18
- public Task < Releaser > LockAsync ( )
18
+ public Task < IDisposable > LockAsync ( )
19
19
{
20
- var wait = semaphore . WaitAsync ( ) ;
21
- return wait . IsCompleted
22
- ? releaser
23
- : wait . ContinueWith (
24
- ( _ , state ) => new Releaser ( ( AsyncLock ) state ) ,
25
- this ,
26
- CancellationToken . None ,
27
- TaskContinuationOptions . ExecuteSynchronously ,
28
- TaskScheduler . Default ) ;
20
+ var wait = _semaphore . WaitAsync ( ) ;
21
+ return wait . IsCompleted ?
22
+ _releaser :
23
+ wait . ContinueWith (
24
+ ( _ , state ) => ( IDisposable ) state ,
25
+ _releaser . Result , CancellationToken . None ,
26
+ TaskContinuationOptions . ExecuteSynchronously , TaskScheduler . Default ) ;
29
27
}
30
28
31
- public struct Releaser : IDisposable
29
+ private sealed class Releaser : IDisposable
32
30
{
33
- private readonly AsyncLock toRelease ;
34
-
35
- internal Releaser ( AsyncLock toRelease )
36
- {
37
- this . toRelease = toRelease ;
38
- }
39
-
40
- public void Dispose ( )
41
- {
42
- if ( toRelease != null )
43
- toRelease . semaphore . Release ( ) ;
44
- }
31
+ private readonly AsyncLock _toRelease ;
32
+ internal Releaser ( AsyncLock toRelease ) { _toRelease = toRelease ; }
33
+ public void Dispose ( ) { _toRelease . _semaphore . Release ( ) ; }
45
34
}
46
35
}
47
36
}
0 commit comments