private TServiceInterface Delay(
     int iteration,
     IDelayPolicy delayPolicy,
     TServiceInterface provider,
     InvokeInfo invokeInfo)
 {
     Thread.Sleep(delayPolicy.GetDelay(iteration));
     return(RefreshProvider(provider, iteration, invokeInfo));
 }
        private async Task <TServiceInterface> DelayAsync(
            int iteration,
            IDelayPolicy delayPolicy,
            TServiceInterface provider,
            InvokeInfo invokeInfo)
        {
            await Task.Delay(delayPolicy.GetDelay(iteration)).ConfigureAwait(false);

            return(RefreshProvider(provider, iteration, invokeInfo));
        }
        public async Task <TResponse> InvokeAsync <TResponse>(Func <TServiceInterface, Task <TResponse> > method, InvokeInfo invokeInfo = null)
        {
            TServiceInterface provider     = RefreshProvider(null, 0, invokeInfo);
            TResponse         lastResponse = default(TResponse);
            IDelayPolicy      delayPolicy  = DelayPolicyFactory();

            var sw = Stopwatch.StartNew();

            try
            {
                this.HandleOnCallBegin(invokeInfo);

                Exception mostRecentException = null;
                for (int i = 0; i < RetryCount + 1; i++)
                {
                    try
                    {
                        this.HandleOnBeforeInvoke(i, invokeInfo);

                        TResponse response = await method(provider).ConfigureAwait(false);

                        this.HandleOnAfterInvoke(i, response, invokeInfo);

                        if (ResponseInRetryable(response))
                        {
                            lastResponse = response;
                            provider     = await DelayAsync(i, delayPolicy, provider, invokeInfo).ConfigureAwait(false);

                            continue;
                        }

                        sw.Stop();

                        response = this.ExecuteResponseHandlers(response);

                        this.HandleOnCallSuccess(sw.Elapsed, response, (i + 1), invokeInfo);

                        return(response);
                    }
                    catch (Exception ex)
                    {
                        this.HandleOnException(ex, i, invokeInfo);

                        // determine whether to retry the service call
                        if (ExceptionIsRetryable(ex))
                        {
                            mostRecentException = ex;

                            provider = await DelayAsync(i, delayPolicy, provider, invokeInfo).ConfigureAwait(false);
                        }
                        else
                        {
                            throw;
                        }
                    }
                }

                if (mostRecentException != null)
                {
                    if (RetryCount == 0)
                    {
                        throw mostRecentException;
                    }

                    var exception = this.RetryFailureExceptionFactory(this.RetryCount, mostRecentException, invokeInfo);
                    throw exception;
                }
            }
            finally
            {
                DisposeProvider(provider, -1, invokeInfo);
            }

            return(lastResponse);
        }