C# HttpClient-如何判断服务器是否关闭得更快?

C# HttpClient-如何判断服务器是否关闭得更快?,c#,.net,http,dotnet-httpclient,C#,.net,Http,Dotnet Httpclient,我正在使用.NETHttpClient向我的服务器发送请求。我已将HttpClient.Timeout属性设置为10秒,因此每当服务器在不到10秒的时间内无法处理我的请求时,就会出现任务被取消异常。在这里之前都很好 但是,如果服务器关闭,HttpClient大约需要20秒才能返回正确的异常,如图中所示 我希望看到此异常的速度超过10秒,以便能够区分服务器停机和操作耗时过长的情况。我在msdn文档中找不到任何与此相关的内容。是否可以在HttpClient上设置超时 下面是我如何构造HttpClie

我正在使用.NET
HttpClient
向我的服务器发送请求。我已将
HttpClient.Timeout
属性设置为10秒,因此每当服务器在不到10秒的时间内无法处理我的请求时,就会出现
任务被取消
异常。在这里之前都很好

但是,如果服务器关闭,
HttpClient
大约需要20秒才能返回正确的异常,如图中所示

我希望看到此异常的速度超过10秒,以便能够区分服务器停机和操作耗时过长的情况。我在msdn文档中找不到任何与此相关的内容。是否可以在
HttpClient
上设置超时

下面是我如何构造
HttpClient

 var webRequestHandler = new WebRequestHandler
        {
            UseProxy = false,
            Proxy = null,
            AllowPipelining = false,
            ContinueTimeout = TimeSpan.Zero,
            UseCookies = false,
            AllowAutoRedirect = false,
        };
 var httpClient = new HttpClient(webRequestHandler);
 httpClient.Timeout = timeout;

  httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Accept", "application/json");
  httpClient.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", userAgent);
  httpClient.DefaultRequestHeaders.ExpectContinue = false;

您无法通过超时处理此问题,如中所述:

域名系统(DNS)查询最多可能需要15秒才能返回或超时。如果您的请求包含需要解析的主机名,并且您将超时设置为小于15秒的值,则可能需要15秒或更长时间才会引发WebException以指示请求超时

但是,另一种方法是将您的请求包装到另一个任务中,并从此处处理超时:

var task = Task.Run(() => { 
                var req = new HttpClient().GetAsync("http://www.google.com");
                if (!req.Wait(10000))//wait for 10 seconds
                    throw new TaskCanceledException(req);
            });
task.Wait();

这个答案只是扩展了@brz的例子

您可以使用这种不阻塞线程的方法(
Task.Wait


我想让你想想一个小类比:如果你在和某人通电话,问一个问题。是否有可靠(快速/即时)的方法来确定与您交谈的人是否睡着了或只是在认真思考?从逻辑上讲,您的问题没有意义,您无法知道您是否因为服务器停机或处理您的请求花费了太长时间而没有得到响应,你只是没有得到回应。我认为这在逻辑上是有意义的,因为有HTTP回应和TCP连接是有区别的。好吧,你可能没有可靠的方法来检查与你交谈的人是否摔倒或思考,但如果你有“如果我在10秒内没有得到回答,请挂断”的规则,采取行动不应花费20秒。请查看ServicePointManager,有一些属性可能会对您有所帮助。另一种选择是使用HttpWebRequest,它有一个启动响应的超时和一个数据到达的超时。
var timeout = Task.Delay(10000); // 10 seconds timeout
var request = httpClient.GetAsync("http://www.google.com");

await Task.WhenAny(timeout, request); // wait for either timeout or the request

if (timeout.IsCompleted) // if the timeout ended first, then handle it
{
    // handle timeout
}

// otherwise continue processing the request result
var response = await request;