使用HttpClient区分超出无服务器响应的时间

时间:2013-12-04 07:46:47

标签: c# .net dotnet-httpclient

有没有办法,使用HttpClient来区分“当我们没有得到服务器的响应时”超时“超出时间”操作?

让我解释一下我们的问题:

  • 案例1:如果我们在10秒内没有收到服务器的任何回复,那么这是一个问题。
  • 案例2:如果我们从服务器获得响应,但服务器继续传输数据,则需要一段时间,可能需要30秒或更长时间。那不是问题。

有没有办法使用.NET HttpClient类来处理这种情况?根据我在HttpClient上指定TimeOut的测试,将为case1和case2设置相同的超时时间。

2 个答案:

答案 0 :(得分:2)

以下是我设法做的解决方案:

// Create the cancelation token, when we don't get any feedback from server within 20 seconds
var cancelHeadersToken = new CancellationTokenSource();
cancelHeadersToken.CancelAfter(TimeSpan.FromSeconds(20)); // if we don't receive server headers after 20 seconds then something went wrong

// We have another cancelation token, that allows the user to cancel the request, so here we create a linked token source which uses both tokens
var linkedToken = CancellationTokenSource.CreateLinkedTokenSource(userCancelToken, cancelHeadersToken.Token);

// The linked token is then used in GetAsync and we use the overload which allows to specify the HttpCompletionOption
// We only want to receive headers and not all content
var httpMessage = await customClient.CustomizedHttpClient.GetAsync(address, HttpCompletionOption.ResponseHeadersRead, linkedToken.Token).ConfigureAwait(false);

// We can then download the content, and we still allow to cancel anything by the user
using (var memoryStream = new MemoryStream(100000)) { // 100ko by default
    using (var stream = await httpMessage.Content.ReadAsStreamAsync().ConfigureAwait(false)) {
        await stream.CopyToAsync(memoryStream, 10000, userCancelToken).ConfigureAwait(false); // copy to memory stream 10ko per 10ko
    }

    string data = "";
    if (memoryStream.Length > 0) {
        var headers = httpMessage.Content.Headers;
        Encoding encoding;
        if (headers != null && headers.ContentType != null && headers.ContentType.CharSet != null) {
            encoding = Encoding.GetEncoding(headers.ContentType.CharSet);
        } else {
            encoding = Encoding.UTF8;
        }
        data = encoding.GetString(memoryStream.GetBuffer(), 0, (int)memoryStream.Length);
    }
    // Then you do whatever you want with data
}               

答案 1 :(得分:1)

您可以使用接受CancellationToken的各种方法的变体之一。

如果方法的Task完成后取消,则会取消取消,您可以继续处理结果中的内容。

var client = new HttpClient();
var cancel = new CancellationTokenSource();
cancel.CancelAfter(TimeSpan.FromSeconds(10));
var resp = client.GetAsync("http://www.google.co.uk", cancel.Token).Result;

因此,在上文中,如果我们从服务器返回足够的GetAsync来完成,则取消无效。