コード例 #1
0
        /// <summary>
        /// Asynchronously acquire a lock on the specified TLockableObject.
        /// This will wait the specified amount of time before either throwing an exception (if throwOnFailure is true) or retuning false.
        /// </summary>
        /// <param name="obj">The object to take a lock on.</param>
        /// <param name="timeout">The amount of time to spend attempting to acquire the lock.</param>
        /// <param name="throwOnFailure">Throw an exception if the acquisition fails.</param>
        /// <param name="cancellationToken">The cancellation token to use during lock acquisition.</param>
        /// <returns>A <see cref="bool"/> indicating if the lock attempt was successful.</returns>
        public async Task <TLockableObject> AcquireLockAsync(TLockableObject obj, TimeSpan timeout, bool throwOnFailure = false, CancellationToken cancellationToken = default(CancellationToken))
        {
            var timeoutDate = DateTime.UtcNow.Add(timeout);

            _lockedObjectType = obj.GetType();
            _lockedObjectId   = obj.Id;

            // TODO: Check if the supplied TLockableObject implements IEnumerable and that they supplied an IEnumerable<TLockableObject> selector.
            TLockableObject lockedObj = null;

            while (lockedObj == null && !cancellationToken.IsCancellationRequested && DateTime.UtcNow < timeoutDate)
            {
                lockedObj = await _store.AcquireLockAsync(obj.Id, obj, _staleLockMultiplier, cancellationToken);

                if (lockedObj == null)
                {
                    await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
                }
                else
                {
                    LockedObjectLockId = lockedObj.LockId;
                    LockedObjectId     = lockedObj.Id;
                }
            }

            _sharpLockLogger.Trace("Lock attempt complete on {0} with LockId: {1}. Lock Acquired? {2}", _lockedObjectType, _lockedObjectId, LockAcquired);

            if (lockedObj == null && throwOnFailure)
            {
                throw new AcquireDistributedLockException("Failed to acquire lock.");
            }

            return(lockedObj);
        }