private void ReleaseLockInternal(LockArgs lockArgs, LockContext context, CloudBlockBlob blob, string leaseId)
        {
            context.AutoRenew = false;
            var releaseTask = new Task(() =>
            {
                blob.ReleaseLease(new AccessCondition() { LeaseId = leaseId });
                if (LockReleased != null) LockReleased(lockArgs);
            });

            if (LockReleaseMode == AzureStorage.LockReleaseMode.Asyncronous)
            {
                releaseTask.Start();
            }
            else if (LockReleaseMode == AzureStorage.LockReleaseMode.Syncronous)
            {
                releaseTask.RunSynchronously();
            }
            else if (LockReleaseMode == AzureStorage.LockReleaseMode.LetExpire)
            {
                // Do nothing
            }
            else
            {
                throw new NotImplementedException("There should not be a possibility for an else");
            }
        }
        private async Task LockInternal(string lockId, string requestId, Action<LockContext> body, int timeLimitInSeconds, DateTime? timeoutTime)
        {
            var lockArgs = new LockArgs(lockId, requestId, 1);
            
            if (timeLimitInSeconds > 0 && (timeLimitInSeconds < 16 || timeLimitInSeconds > 59))
            {
                throw new ArgumentException("timeLimitInSeconds must be at least 16 and no greater than 59");
            }

            CloudBlockBlob blob = container.GetBlockBlobReference(lockId);
            if (blob.Exists() == false)
            {
                MemoryStream ms = new MemoryStream();
                blob.UploadFromStream(ms);
            }

            var lockContext = new LockContext(blob, null);
            bool gotLock = false;
            string leaseId = null;
            while (gotLock == false)
            {
                try
                {
                    TimeSpan? maxLeaseTime = null;
                    if (timeLimitInSeconds > 0) maxLeaseTime = TimeSpan.FromSeconds(timeLimitInSeconds);
             
                    string proposedLeaseId = null;
                    object state = null;
                    
                    leaseId = await Task<string>.Factory.FromAsync(blob.BeginAcquireLease, blob.EndAcquireLease, maxLeaseTime, proposedLeaseId, state, TaskCreationOptions.None);
                    lockContext.LeaseId = leaseId;
                    lockContext.AutoRenew = this.AutoRenew;
                    lockContext.LockRenewed += (context) => { if (LockRenewed != null) LockRenewed(lockArgs); };
                    gotLock = true;

                    if (maxLeaseTime.HasValue)
                    {
                        lockContext.LockWarningTimerDuration = maxLeaseTime.Value - ExpiryWarningThreshold;
                        lockContext.LockWarningTimer = new Timer((o) =>
                        {
                            if (LeaseNearExpiry != null) LeaseNearExpiry(lockArgs, lockContext);
                        }, null, (int)lockContext.LockWarningTimerDuration.TotalMilliseconds, Timeout.Infinite);
                    }

                    if (LockAcquired != null) LockAcquired(lockArgs);
                    body(new LockContext(blob,leaseId));
                    if(lockContext.LockWarningTimer != null) lockContext.LockWarningTimer.Dispose();
                }
                catch (StorageException ex)
                {
                    var innerWeb = ex.InnerException as WebException;
                    if (innerWeb == null) throw;
                    var response = innerWeb.Response as HttpWebResponse;
                    if (response == null) throw;
                    if (response.StatusCode != HttpStatusCode.Conflict) throw;
                    if (timeoutTime.HasValue && DateTime.UtcNow > timeoutTime.Value)
                    {
                        throw GetTimeoutExceptionInternal();
                    };
                }
                finally
                {
                    if(gotLock) ReleaseLockInternal(lockArgs, lockContext, blob, leaseId);
                }

                if (gotLock == false)
                {
                    if (LockWaiting != null) LockWaiting(lockArgs);
                    lockArgs.AttemptNumber++;
                    await Task.Delay(PollingInterval);
                }
            }
        }