public IAsyncResult BeginSend(ServiceRequest request, ExecutionContext context,
                                      AsyncCallback callback, object state)
        {
            var asyncResult = new RetryableAsyncResult(callback, state, request, context);

            BeginSendImpl(request, context, asyncResult);

            return(asyncResult);
        }
 private void BeginSendImpl(ServiceRequest request, ExecutionContext context,
                            RetryableAsyncResult asyncResult)
 {
     if (asyncResult.InnerAsyncResult != null)
     {
         asyncResult.InnerAsyncResult.Dispose();
     }
     asyncResult.InnerAsyncResult =
         _innerClient.BeginSend(request, context, asyncResult.Callback, asyncResult) as AsyncResult;
 }
        public ServiceResponse EndSend(IAsyncResult ar)
        {
            if (ar == null)
            {
                throw new ArgumentNullException("ar");
            }

            var asyncResult = ar as AsyncResult <ServiceResponse>;
            RetryableAsyncResult retryableAsyncResult = ar.AsyncState as RetryableAsyncResult;

            if (asyncResult == null || retryableAsyncResult == null)
            {
                throw new InvalidOperationException("Invalid asynchronous invocation status.");
            }

            try
            {
                var response = asyncResult.GetResult();
                return(response);
            }
            catch (Exception ex)
            {
                if (retryableAsyncResult.OriginalContentPosition >= 0)
                {
                    retryableAsyncResult.Request.Content.Seek(retryableAsyncResult.OriginalContentPosition,
                                                              SeekOrigin.Begin);
                }

                if (ShouldRetry(retryableAsyncResult.Request, ex, retryableAsyncResult.Retries))
                {
                    Pause(retryableAsyncResult.Retries++);
                    BeginSendImpl(retryableAsyncResult.Request, retryableAsyncResult.Context, retryableAsyncResult);
                }

                // Rethrow
                throw;
            }
            finally
            {
                asyncResult.Dispose();
            }
        }