Beispiel #1
0
        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);
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        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
                    );
            }
        }
Beispiel #4
0
        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);
        }
Beispiel #5
0
        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);
        }
Beispiel #6
0
        private async Task AcquireMutexAsync()
        {
            _acquisitionResult = await Task.Run(() =>
            {
                Debug.WriteLine("-----------------------ThreadId = " + Environment.CurrentManagedThreadId);
                return(_mutex.AcquireAsync(_msec));
            });

            MutexStatus = _acquisitionResult.ToString();
        }
Beispiel #7
0
        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));
        }
Beispiel #8
0
        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());
                    }
                }
            }
        }
Beispiel #10
0
        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);
        }
Beispiel #11
0
        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);
        }