重试HttpClient的请求不成功 [英] Retrying HttpClient Unsuccessful Requests
问题描述
我构建给予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屋!