private async Task <MutexOperationResult> ForceClearIfTimeoutExpired() { var result = new MutexOperationResult(); try { var file = await GetFile(); if (file != null) { var currentTime = DateTime.Now; var fileTimeStamp = file.DateCreated; if ((currentTime - fileTimeStamp).TotalMilliseconds > TIMEOUT_MSEC * 2) { var cleared = await ClearAsync(); result.Combine(cleared); Debug.WriteLine("-------Force clear: " + cleared.ToString()); } } else { result.Result = MutexOperationResultEnum.Free; } } catch { result.Result = MutexOperationResultEnum.ExceptionFileSystem | MutexOperationResultEnum.FailToClear; } return(result); }
public async Task <MutexOperationResult> ReleaseAsync(string key) { var released = new MutexOperationResult(); var file = await GetFile(); if (file == null) { released.Result = MutexOperationResultEnum.Free; } else { var mutexKey = await FileIO.ReadTextAsync(file); if (mutexKey == key) { await file.DeleteAsync(); released.AcquisitionKey = key; released.Result = MutexOperationResultEnum.Released; CancelDeferredMutexRelease(); } else { released.Result = MutexOperationResultEnum.FailToRelease; } } return(released); }
private void SetDeferredMutexRelease(MutexOperationResult result) { if (result.ResultIs(MutexOperationResultEnum.Acquired)) { _deferredReleaseCancellationSource = new CancellationTokenSource(); var deferredReleaseCancellationToken = _deferredReleaseCancellationSource.Token; _deferredRelease = Task.Run( async() => { var checkIfCancelledPeriod = 1000; for (var i = 0; i < TIMEOUT_MSEC / checkIfCancelledPeriod; i++) { await Task.Delay(checkIfCancelledPeriod); if (deferredReleaseCancellationToken.IsCancellationRequested) { Debug.WriteLine("-------Deferred release: cancel"); deferredReleaseCancellationToken.ThrowIfCancellationRequested(); } else { Debug.WriteLine("-------Deferred release: waiting " + (i * 1000).ToString()); } } var released = await ReleaseAsync(result.AcquisitionKey); Debug.WriteLine("-------Deferred release: " + released.ToString()); } , deferredReleaseCancellationToken ); } }
public MutexOperationResult Acquire(int milliseconds = 0) { Mutex mutex = null; var result = new MutexOperationResult(); mutex = OpenExisting(); if (mutex == null) { mutex = CreateMutex(); if (mutex == null) { result.Result = MutexOperationResultEnum.FailToCreate; } else { result.Result = MutexOperationResultEnum.Acquired; } } else { result.Result = MutexOperationResultEnum.Acquired; } result.Result = result.Result | Acquire(mutex, milliseconds).Result; return(result); }
public async Task <MutexOperationResult> ClearAsync() { var cleared = new MutexOperationResult(); try { var file = await GetFile(); if (file != null) { await file.DeleteAsync(); cleared.Result = MutexOperationResultEnum.Cleared; CancelDeferredMutexRelease(); } else { cleared.Result = MutexOperationResultEnum.Free; } } catch { cleared.Result = MutexOperationResultEnum.ExceptionFileSystem | MutexOperationResultEnum.FailToClear; } return(cleared); }
private async Task AcquireMutexAsync() { _acquisitionResult = await Task.Run(() => { Debug.WriteLine("-----------------------ThreadId = " + Environment.CurrentManagedThreadId); return(_mutex.AcquireAsync(_msec)); }); MutexStatus = _acquisitionResult.ToString(); }
public MutexOperationResult Release(bool forceDisposeIfNotReleased = false) { var mutex = OpenExisting(); if (mutex == null) { var result = new MutexOperationResult(); result.Result = MutexOperationResultEnum.FailToRelease; return(result); } return(Release(mutex, forceDisposeIfNotReleased)); }
private MutexOperationResult Release(Mutex mutex, bool forceDisposeIfNotReleased = false) { var mutexReleased = new MutexOperationResult(); if (mutex != null) { try { mutex.ReleaseMutex(); mutexReleased.Result = MutexOperationResultEnum.Released; } catch (Exception ex) { // getting here following ex: // "object synchronization method was called from an unsynchronized block of code" if (ex.HResult == SYNCHRONIZATION_EX_HRESULT) { mutexReleased.Result = MutexOperationResultEnum.ExceptionUnknown; } else { mutexReleased.Result = MutexOperationResultEnum.ExceptionUnknown; } } try { if (mutexReleased.Result != MutexOperationResultEnum.Released && forceDisposeIfNotReleased) { mutex.Dispose(); mutexReleased.Result = MutexOperationResultEnum.Cleared; } } catch (Exception ex) { Debug.WriteLine(ex.ToString()); mutexReleased.Result = MutexOperationResultEnum.FailToClear; } } else { //attempt to release unexisting mutex mutexReleased.Result = MutexOperationResultEnum.FailToClear; } return(mutexReleased); }
private async Task Run() { Debug.WriteLine("--------------------FbmBackgroundTask.Run(): Start"); //IMutex mutex = new RefreshTokenMutex(); IMutexService mutex = new MutexService(); MutexOperationResult mutexAcquired = null; MutexOperationResult mutexReleased = null; try { Debug.WriteLine("--------------------FbmBackgroundTask.Run(): enter mutex"); mutexAcquired = await mutex.AcquireAsync(5000); Debug.WriteLine("--------------------FbmBackgroundTask.Run():" + mutexAcquired.ToString()); if ((mutexAcquired.Result & MutexOperationResultEnum.Acquired) != MutexOperationResultEnum.NoValue) { // Do work here for (var i = 0; i < 10; i++) { await Task.Delay(1000); Debug.WriteLine("--------------------FbmBackgroundTask.Run():" + "doing some work"); } } } catch (Exception ex) { Debug.WriteLine("--------------------FbmBackgroundTask.Run(): exception {0}", ex.ToString()); } finally { if (mutexAcquired != null && mutexAcquired.ResultIs(MutexOperationResultEnum.Acquired)) { mutexReleased = await mutex.ReleaseAsync(mutexAcquired.AcquisitionKey); Debug.WriteLine("--------------------FbmBackgroundTask.Run(): " + mutexReleased.ToString()); if (mutexReleased == null || !mutexReleased.ResultIs(MutexOperationResultEnum.Released)) { var mutexCleared = await mutex.ClearAsync(); Debug.WriteLine("--------------------FbmBackgroundTask.Run(): " + "Clear: " + mutexCleared.ToString()); } } } }
private MutexOperationResult Acquire(Mutex mutex, int milliseconds = 0) { MutexOperationResult mutexAcquired = new MutexOperationResult(); if (mutex != null) { try { if (mutex.WaitOne(milliseconds)) { mutexAcquired.Result = MutexOperationResultEnum.Acquired; } else { mutexAcquired.Result = MutexOperationResultEnum.FailToAcquire; } } catch (AbandonedMutexException) { // we may try to recover mutexAcquired.Result = MutexOperationResultEnum.ExceptionUnknown; mutex.Dispose(); mutexAcquired.Result = mutexAcquired.Result | MutexOperationResultEnum.Cleared; mutex = CreateMutex(); if (mutex != null) { mutexAcquired.Result = mutexAcquired.Result | MutexOperationResultEnum.Acquired; if (mutex.WaitOne(milliseconds)) { mutexAcquired.Result = mutexAcquired.Result | MutexOperationResultEnum.Acquired; } else { mutexAcquired.Result = mutexAcquired.Result | MutexOperationResultEnum.FailToAcquire; } } else { mutexAcquired.Result = mutexAcquired.Result | MutexOperationResultEnum.FailToCreate; } } } return(mutexAcquired); }
public async Task <MutexOperationResult> AcquireAsync(int milliseconds = 0) { var result = new MutexOperationResult(); StorageFile file = null; try { file = await GetFile(); } catch { result.Result = MutexOperationResultEnum.ExceptionFileSystem; return(result); } if (file == null) { try { result.Result = MutexOperationResultEnum.Free; var key = Guid.NewGuid().ToString(); file = await Folder.CreateFileAsync(FILE); await FileIO.WriteTextAsync(file, key); result.AcquisitionKey = key; result.Result = MutexOperationResultEnum.Acquired; SetDeferredMutexRelease(result); // Will launch task which release mutex when timeout } catch (Exception) { result.Result = MutexOperationResultEnum.ExceptionFileSystem; } } else { // First attempt to intercept mutex: force clear if mutex Acquired longer then TIMEOUT var forcedCleared = await ForceClearIfTimeoutExpired(); if (forcedCleared.ResultIs(MutexOperationResultEnum.Cleared)) { var forcedAcquired = await AcquireAsync(); result.Combine(forcedCleared); result.Combine(forcedAcquired); return(result); } // Second attempt to intercept mutex: await specifyed delay if (milliseconds >= 1000) { for (var i = 0; i < Math.Min(milliseconds, TIMEOUT_MSEC) / 1000; i++) // There is no need to wait longer then TIMEOUT, // if mutex not released it indicates greater failure { await Task.Delay(1000); var delayedAcquired = await AcquireAsync(); result.Combine(delayedAcquired); if (delayedAcquired.ResultIs(MutexOperationResultEnum.Acquired)) { return(result); } } result.Result = MutexOperationResultEnum.FailToAcquire; } } return(result); }