【发布时间】:2019-05-24 07:41:12
【问题描述】:
我像这样初始化HttpClient:
public static CookieContainer cookieContainer = new CookieContainer();
public static HttpClient httpClient = new HttpClient(new HttpClientHandler() { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate, CookieContainer = cookieContainer }) { Timeout = TimeSpan.FromSeconds(120) };
所以如果在 120 秒内没有收到响应,所有查询都应该抛出 TaskCanceledException。
但有些查询(例如 1 万个 100 000-1 000 000 个)会无限挂起。
我写了以下代码:
public static async Task<HttpResponse> DownloadAsync2(HttpRequestMessage httpRequestMessage)
{
HttpResponse response = new HttpResponse { Success = false, StatusCode = (int)HttpStatusCode.RequestTimeout, Response = "Timeout????????" };
Task task;
if (await Task.WhenAny(
task = Task.Run(async () =>
{
try
{
HttpResponseMessage r = await Global.httpClient.SendAsync(httpRequestMessage).ConfigureAwait(false);
response = new HttpResponse { Success = true, StatusCode = (int)r.StatusCode, Response = await r.Content.ReadAsStringAsync().ConfigureAwait(false) };
}
catch (TaskCanceledException)
{
response = new HttpResponse { Success = false, StatusCode = (int)HttpStatusCode.RequestTimeout, Response = "Timeout" };
}
catch (Exception ex)
{
response = new HttpResponse { Success = false, StatusCode = -1, Response = ex.Message + ": " + ex.InnerException };
}
}),
Task.Run(async () =>
{
await Task.Delay(TimeSpan.FromSeconds(150)).ConfigureAwait(false);
})
).ConfigureAwait(false) != task)
{
Log("150 seconds passed");
}
return response;
}
实际上偶尔会执行Log("150 seconds passed");。
我这样称呼它:
HttpResponse r = await DownloadAsync2(new HttpRequestMessage
{
RequestUri = new Uri("https://address.com"),
Method = HttpMethod.Get
}).ConfigureAwait(false);
为什么 TaskCanceledException 有时在 120 秒后不抛出?
【问题讨论】:
-
这是我见过的在一定时间后取消请求的最复杂的代码。
-
await Task.WhenAny只是防止我的任务卡住的解决方法。根本不应该使用它。但首先我需要弄清楚为什么 try 块中的代码有时会无限挂起。 -
如果它卡住了,那么您的代码中的其他地方就会出现不同的问题。您是否在代码中的某个地方使用了
task.Result? -
我不会在代码中的任何地方使用
task.Result。我添加了如何使用DownloadAsync2方法的代码。 -
调用该代码的代码是什么?如果在代码中的任何位置调用
.Result,它可能会导致它死锁并永远挂起。
标签: c# async-await timeout httpclient