コード例 #1
0
ファイル: AsyncMutex.cs プロジェクト: tsellers33/WalletWasabi
        private void ReleaseLock()
        {
            if (!IsAlive)
            {
                throw new InvalidOperationException("Thread should be alive.");
            }

            // On multiply call we will get an exception. This is not a dispose so we can throw here.
            ChangeStatus(AsyncLockStatus.StatusReleasing, AsyncLockStatus.StatusAcquired);

            StopThread();

            ChangeStatus(AsyncLockStatus.StatusReady, AsyncLockStatus.StatusReleasing);
            // Release the local lock.
            AsyncLock?.ReleaseLock();
        }
コード例 #2
0
        /// <summary>
        /// The Lock mechanism designed for standard using blocks. This lock is thread and interprocess safe.
        /// You can create and use it from anywhere.
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <param name="pollInterval">The frequency of polling the termination of the mutex-thread.</param>
        /// <returns>The IDisposable await-able Task.</returns>
        public async Task <IDisposable> LockAsync(CancellationToken cancellationToken = default, int pollInterval = 100)
        {
            Exception inner = null;

            try
            {
                if (IsQuitPending)
                {
                    throw new OperationCanceledException($"{nameof(AsyncMutex)}.{nameof(AsyncMutex.LockAsync)} failed because quit is pending on: {ShortName}.");
                }

                // Local lock for thread safety.
                await AsyncLock.LockAsync(cancellationToken);

                if (IsAlive)
                {
                    throw new InvalidOperationException("Thread should not be alive.");
                }

                MutexThread = new Thread(new ParameterizedThreadStart(HoldLock))
                {
                    Name = $"{nameof(MutexThread)}"
                };

                MutexThread.Start(cancellationToken);

                ChangeStatus(AsyncLockStatus.StatusAcquiring, AsyncLockStatus.StatusReady);

                // Thread is running from now.

                try
                {
                    // Create the mutex and acquire it.
                    await SetCommandAsync(1, cancellationToken, pollInterval);
                }
                catch (Exception ex)
                {
                    Logger.LogWarning(ex);
                    // If the thread is still alive we must stop it
                    StopThread();

                    ChangeStatus(AsyncLockStatus.StatusReady, AsyncLockStatus.StatusAcquiring);

                    throw ex;
                }

                ChangeStatus(AsyncLockStatus.StatusAcquired, AsyncLockStatus.StatusAcquiring);

                return(new Key(this));
            }
            catch (TaskCanceledException)
            {
                // Let it go.
            }
            catch (AbandonedMutexException)
            {
                // abandoned mutexes are still acquired, we just need
                // to handle the exception and treat it as acquisition
                Logger.LogWarning($"{nameof(AbandonedMutexException)} in {ShortName}.");
                return(new Key(this));
            }
            catch (Exception ex)
            {
                Logger.LogError($"{ex.ToTypeMessageString()} in {ShortName}.");
                inner = ex;
                // Let it go.
            }

            // Release the local lock.
            AsyncLock.ReleaseLock();

            throw new IOException($"Could not acquire system wide mutex on {ShortName}.", inner);
        }
コード例 #3
0
ファイル: AsyncLock.cs プロジェクト: Nucs/nlib
 /// <summary>
 /// Release the lock.
 /// </summary>
 public void Dispose()
 {
     _asyncLock.ReleaseLock();
 }