/// <summary> /// Attempts to acquire the lock synchronously. Usage: /// <code> /// using (var handle = myLock.TryAcquire(...)) /// { /// if (handle != null) { /* we have the lock! */ } /// } /// // dispose releases the lock if we took it /// </code> /// </summary> /// <param name="timeout">How long to wait before giving up on acquiring the lock. Defaults to 0</param> /// <param name="cancellationToken">Specifies a token by which the wait can be canceled</param> /// <returns>An <see cref="IDisposable"/> "handle" which can be used to release the lock, or null if the lock was not taken</returns> public IDisposable TryAcquire(TimeSpan timeout = default(TimeSpan), CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.CanBeCanceled) { // use the async version since that supports cancellation return(DistributedLockHelpers.TryAcquireWithAsyncCancellation(this, timeout, cancellationToken)); } // synchronous mode var timeoutMillis = timeout.ToInt32Timeout(); DbConnection connection = null; DbTransaction transaction = null; var cleanup = true; try { connection = this.GetConnection(); if (this.connectionString != null) { connection.Open(); } else if (connection == null) { throw new InvalidOperationException("The transaction had been disposed"); } else if (connection.State != ConnectionState.Open) { throw new InvalidOperationException("The connection is not open"); } transaction = this.GetTransaction(connection); SqlParameter returnValue; using (var command = CreateAcquireCommand(connection, transaction, this.lockName, timeoutMillis, out returnValue)) { command.ExecuteNonQuery(); var exitCode = (int)returnValue.Value; if (ParseExitCode(exitCode)) { cleanup = false; return(new LockScope(this, transaction)); } return(null); } } catch { // in case we fail to create lock scope or something cleanup = true; throw; } finally { if (cleanup) { this.Cleanup(transaction, connection); } } }
/// <summary> /// Attempts to acquire the lock synchronously. Usage: /// <code> /// using (var handle = myLock.TryAcquire(...)) /// { /// if (handle != null) { /* we have the lock! */ } /// } /// // dispose releases the lock if we took it /// </code> /// </summary> /// <param name="timeout">How long to wait before giving up on acquiring the lock. Defaults to 0</param> /// <param name="cancellationToken">Specifies a token by which the wait can be canceled</param> /// <returns>An <see cref="IDisposable"/> "handle" which can be used to release the lock, or null if the lock was not taken</returns> public IDisposable TryAcquire(TimeSpan timeout = default(TimeSpan), CancellationToken cancellationToken = default(CancellationToken)) { return(cancellationToken.CanBeCanceled // use the async version since that supports cancellation ? DistributedLockHelpers.TryAcquireWithAsyncCancellation(this, timeout, cancellationToken) // synchronous mode : this.internalLock.TryAcquire(timeout.ToInt32Timeout(), SqlApplicationLock.Mode.Exclusive, contextHandle: null)); }