重试HttpClient的请求不成功 [英] Retrying HttpClient Unsuccessful Requests

查看:2119
本文介绍了重试HttpClient的请求不成功的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我构建给予HttpContent对象的函数,将问题要求,然后重试失败。不过,我得到异常说HttpContent对象发出请求后处理。反正是有复制或复制HttpContent对象,这样我可以发出多个请求。

 公共HttpResponseMessage ExecuteWithRetry(字符串URL,HttpContent内容)
{
HttpResponseMessage结果= NULL;
BOOL成功= FALSE;
用做
{
(VAR的客户=新的HttpClient())
{
结果= client.PostAsync(URL,内容)。结果;
成功= result.IsSuccessStatusCode;
}
}
,而(成功!);

返回结果;
}

//也不例外工作,如果第一个请求是成功的
ExecuteWithRetry(http://www.requestb.in/xfxcva/ *有效的URL * /新的StringContent(的Hello World));
//抛出,如果请求被重试...
ExecuteWithRetry(http://www.requestb.in/badurl/ *无效的URL * /,新的StringContent(Hello World的) );



(很显然,我不下去尝试,但上面的代码基本上是我想要什么)。



它会产生此异常

  System.AggregateException:出现一个或多个错误。 ---> System.ObjectDisposedException:无法访问已释放的对象。 
对象名称:'System.Net.Http.StringContent。在System.Net.Http.HttpContent.CheckDisposed
()
在System.Net.Http.HttpContent.CopyToAsync(流流,TransportContext上下文)
在System.Net.Http.HttpClientHandler。 GetRequestStreamCallback(IAsyncResult的AR)
---内部异常堆栈跟踪---
在System.Threading.Tasks.Task.ThrowIfExceptional(布尔includeTaskCanceledExceptions)
在System.Threading.Tasks结束。 Task`1.GetResultCore(布尔waitCompletionNotification)
在System.Threading.Tasks.Task`1.get_Result()
在提交#8.ExecuteWithRetry(字符串URL,HttpContent内容)

反正是有重复的HttpContent对象或重用呢?


解决方案

无需实现重试包装了的HttpClient ,可考虑构建功能的的HttpClient HttpMessageHandler 在内部进行了重试逻辑。例如:



<预类=郎-CS prettyprint-覆盖> 公共类RetryHandler:DelegatingHandler
{
//强烈考虑限制重试次数 - 重试永远是
//可能不是最用户友好的方式,你可以回应的
//网线得到了拔出。
私人const int的MaxRetries = 3;

公共RetryHandler(HttpMessageHandler innerHandler)
:基地(innerHandler)
{}

保护覆盖异步任务< HttpResponseMessage> SendAsync(
HttpRequestMessage要求,
的CancellationToken的CancellationToken)
{
HttpResponseMessage响应;
的for(int i = 0; I< MaxRetries;我++)
{
响应=等待base.SendAsync(请求的CancellationToken);
如果(response.IsSuccessStatusCode){
返回响应;
}
}

返回响应;
}
}

公共类BusinessLogic
{
公共无效FetchSomeThingsSynchronously()
{
// ...

//考虑使用(VAR的客户=新的HttpClient(新RetryHandler(新HttpClientHandler())))这个抽象建造工厂或IoC容器

{
myResult = client.PostAsync(yourUri,yourHttpContent)。结果;
}

// ...
}
}


I am building a function that given an HttpContent Object, will issues request and retry on failure. However I get exceptions saying that HttpContent Object is disposed after issuing the request. Is there anyway to copy or duplicate the HttpContent Object so that I can issue multiple requests.

 public HttpResponseMessage ExecuteWithRetry(string url, HttpContent content)
 {
  HttpResponseMessage result = null;
  bool success = false;
  do
  {
      using (var client = new HttpClient())
      {
          result = client.PostAsync(url, content).Result;
          success = result.IsSuccessStatusCode;
      }
  }
  while (!success);

 return result;
} 

// Works with no exception if first request is successful
ExecuteWithRetry("http://www.requestb.in/xfxcva" /*valid url*/, new StringContent("Hello World"));
// Throws if request has to be retried ...
ExecuteWithRetry("http://www.requestb.in/badurl" /*invalid url*/, new StringContent("Hello World"));

(Obviously I don't try indefinitely but the code above is essentially what i want).

It yields this exception

System.AggregateException: One or more errors occurred. ---> System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'System.Net.Http.StringContent'.
   at System.Net.Http.HttpContent.CheckDisposed()
   at System.Net.Http.HttpContent.CopyToAsync(Stream stream, TransportContext context)
   at System.Net.Http.HttpClientHandler.GetRequestStreamCallback(IAsyncResult ar)
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at System.Threading.Tasks.Task`1.get_Result()
   at Submission#8.ExecuteWithRetry(String url, HttpContent content)

Is there anyway to duplicate an HttpContent Object or reuse it?

解决方案

Instead of implementing retry functionality that wraps the HttpClient, consider constructing the HttpClient with a HttpMessageHandler that performs the retry logic internally. For example:

public class RetryHandler : DelegatingHandler
{
    // Strongly consider limiting the number of retries - "retry forever" is
    // probably not the most user friendly way you could respond to "the
    // network cable got pulled out."
    private const int MaxRetries = 3;

    public RetryHandler(HttpMessageHandler innerHandler)
        : base(innerHandler)
    { }

    protected override async Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request,
        CancellationToken cancellationToken)
    {
        HttpResponseMessage response;
        for (int i = 0; i < MaxRetries; i++)
        {
            response = await base.SendAsync(request, cancellationToken);
            if (response.IsSuccessStatusCode) {
                return response;
            }
        }

        return response;
    }
}

public class BusinessLogic
{
    public void FetchSomeThingsSynchronously()
    {
        // ...

        // Consider abstracting this construction to a factory or IoC container
        using (var client = new HttpClient(new RetryHandler(new HttpClientHandler())))
        {
            myResult = client.PostAsync(yourUri, yourHttpContent).Result;
        }

        // ...
    }
}

这篇关于重试HttpClient的请求不成功的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆