/// <summary>
        /// Method to force the refresh of a cached secret state.
        /// Returns true if the refresh completed without error.
        /// </summary>
        public async Task <bool> RefreshNowAsync()
        {
            refreshNeeded = true;
            // When forcing a refresh, always sleep with a random jitter
            // to prevent coding errors that could be calling refreshNow
            // in a loop.
            long sleep = FORCE_REFRESH_JITTERED_DELAY.GetRetryDelay(1).Milliseconds;

            // Make sure we are not waiting for the next refresh after an
            // exception.  If we are, sleep based on the retry delay of
            // the refresh to prevent a hard loop in attempting to refresh a
            // secret that continues to throw an exception such as AccessDenied.
            if (null != exception)
            {
                long wait = nextRetryTime - Environment.TickCount;
                sleep = Math.Max(wait, sleep);
            }
            Thread.Sleep((int)sleep);

            // Perform the requested refresh.
            bool success = false;
            await Lock.WaitAsync();

            try
            {
                success = await RefreshAsync();
            }
            finally
            {
                Lock.Release();
            }
            return(null == exception && success);
        }
        /// <summary>
        /// Refresh the cached secret state only when needed.
        /// </summary>
        private async Task <bool> RefreshAsync()
        {
            if (!IsRefreshNeeded())
            {
                return(false);
            }
            refreshNeeded = false;
            try
            {
                SetResult(await ExecuteRefreshAsync());
                exception      = null;
                exceptionCount = 0;
                return(true);
            }
            catch (Exception ex) when(ex is AmazonServiceException || ex is AmazonClientException)
            {
                exception = ex;
                // Determine the amount of growth in exception backoff time based on the growth
                // factor and default backoff duration.

                nextRetryTime = Environment.TickCount + EXCEPTION_JITTERED_DELAY.GetRetryDelay((int)exceptionCount).Milliseconds;
            }
            return(false);
        }