From b52439f8f165acb7195de246ca73a88c4dff6b1a Mon Sep 17 00:00:00 2001 From: Stephan Date: Fri, 3 Jul 2015 15:31:51 +0200 Subject: [PATCH] AsyncLock - support timeout when async-locking --- src/Umbraco.Core/AsyncLock.cs | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Core/AsyncLock.cs b/src/Umbraco.Core/AsyncLock.cs index 0a9c79a80e..608b19a700 100644 --- a/src/Umbraco.Core/AsyncLock.cs +++ b/src/Umbraco.Core/AsyncLock.cs @@ -63,13 +63,13 @@ namespace Umbraco.Core // for anonymous semaphore, use the unique releaser, else create a new one return _semaphore != null ? _releaser // (IDisposable)new SemaphoreSlimReleaser(_semaphore) - : (IDisposable)new NamedSemaphoreReleaser(_semaphore2); + : new NamedSemaphoreReleaser(_semaphore2); } public Task LockAsync() { var wait = _semaphore != null - ? _semaphore.WaitAsync() + ? _semaphore.WaitAsync() : WaitOneAsync(_semaphore2); return wait.IsCompleted @@ -79,6 +79,19 @@ namespace Umbraco.Core TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default); } + public Task LockAsync(int millisecondsTimeout) + { + var wait = _semaphore != null + ? _semaphore.WaitAsync(millisecondsTimeout) + : WaitOneAsync(_semaphore2, millisecondsTimeout); + + return wait.IsCompleted + ? _releaserTask ?? Task.FromResult(CreateReleaser()) // anonymous vs named + : wait.ContinueWith((_, state) => (((AsyncLock)state).CreateReleaser()), + this, CancellationToken.None, + TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default); + } + public IDisposable Lock() { if (_semaphore != null) @@ -174,7 +187,7 @@ namespace Umbraco.Core // F# has a AwaitWaitHandle method that accepts a time out... and seems pretty complex... // version below should be OK - private static Task WaitOneAsync(WaitHandle handle) + private static Task WaitOneAsync(WaitHandle handle, int millisecondsTimeout = Timeout.Infinite) { var tcs = new TaskCompletionSource(); var callbackHandleInitLock = new object(); @@ -197,7 +210,7 @@ namespace Umbraco.Core } }, /*state:*/ null, - /*millisecondsTimeOutInterval:*/ Timeout.Infinite, + /*millisecondsTimeOutInterval:*/ millisecondsTimeout, /*executeOnlyOnce:*/ true); }