C# 中 Timeout 的處理
前言
最近在專案中要實現一個功能,是關於 Timeout
的,主要是要在要在 TCP 連線建立的時間 和 整個請求完成的時間,在這兩個時間層面上,如果超出了設定的時間,就丟擲異常,程式中斷。
研究了一下專案的程式碼中,發現在使用HTTP協議,傳送請求時,主要用的是微軟的 Microsoft.Net.HttpWebRequest
這個類來發起請求和接收請求的。當時我隱約記得這個類怎麼有點熟悉呀,好像還有 WebRequst
和 HttpClient
這兩個把,還沒開始真正開始去瞭解Timeout
在HttpWebRequest
中 如何實現的,我先去看了看這三者到底有何不同?
WebRequest , HttpWebRequest , HttpClient
WebRequest 是 一個抽象類,是HttpWebRequest
的父類。是.NET
中請求和獲取網路中的資料的一個類。
HttpWebRequest 是WebReques
t 的一個實現,不僅對WebRequest
中的屬性和方法進行了支援,而且還有額外的方法透過Http
協議來和服務端互動。
上面那兩個現在在微軟官方檔案上都不推薦使用了,
現在所推薦的是 HttpClient
。由於專案中遺留之前使用的是HttpWebRequest
,所以就在原來的基礎上進行實現,何況的是在HttpClient
中沒有找到TCP
連線建立的時間屬性的設定。
HttpClient 優點自不必多說:
- 連線池
- 一次初始化,整個生命週期的重用
- 和 .Net Core 的融合
- 以及效能的提升等等
雖然說效能可能提升了,如果你這樣用,那也是涼涼
using(HttpClient clinet = new HttpClient())
{
var result = await client.GetAsync("http://aspnetmonsters.com");
Console.WriteLine(result.StatusCode);
}
用完 Using
後,呼叫了IDispose
介面。那下次還是會重新初始化
這樣使用就沒問題了
private static HttpClient Client = new HttpClient();
Timeout, ReadWriteTimeout
也可能是我英文的理解能力有點差,在開始我就註意到這個類裡面的這兩個屬性,但是我如何也無法和 TCP 建立前所用的連線時間 與 請求完成的時間聯絡起來。微軟官方檔案解釋如下:
Timeout:
Timeout is the number of milliseconds that a subsequent synchronous request made with the GetResponse method waits for a response, and the GetRequestStream method waits for a stream. The Timeout applies to the entire request and response, not individually to the GetRequestStreamand GetResponse method calls. If the resource is not returned within the time-out period, the request throws a WebException with the Status property set to WebExceptionStatus.Timeout.
The Timeout property has no effect on asynchronous requests made with the BeginGetResponse or BeginGetRequestStream method.
ReadWriteTimeout:
The ReadWriteTimeout property is used when writing to the stream returned by the GetRequestStream method or reading from the stream returned by the GetResponseStream method.
Specifically, the ReadWriteTimeout property controls the time-out for the Read method, which is used to read the stream returned by the GetResponseStream method, and for the Write method, which is used to write to the stream returned by the GetRequestStream method.
設定其實是很方便的,如下所示:
HttpWebRequest request = (HttpWebRequest)WebRequest.Creat("");
request.Timeout = 1000;
request.ReadWriteTimeout = 3000;
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
WebClient.Exception.Timeout 和 OperationCanceledException
最後在捕捉異常的時候,發現了一個很奇怪的地方,就是使用兩段程式碼,卻丟擲了不同的異常,
第一段程式碼:
HttpWebRequest request = (HttpWebRequest) WebRequest.Create("https://www.alibabacloud.com");
request.Timeout = 5000;
HttpWebResponse response = (HttpWebResponse) request.GetResponse();
HttpWebRequest request2 = (HttpWebRequest) WebRequest.Create("https://www.cnblogs.com");
request2.Timeout = 1;
HttpWebResponse response2 = (HttpWebResponse) request2.GetResponse();
第二段
HttpWebRequest request = (HttpWebRequest) WebRequest.Create("https://www.alibabacloud.com");
request.Timeout = 5000;
HttpWebResponse response = (HttpWebResponse) request.GetResponse();
request = (HttpWebRequest) WebRequest.Create("https://www.cnblogs.com");
request.Timeout = 1;
response = (HttpWebResponse) request.GetResponse();
初步估計的原因是,Http 請求中 Keep-Alive的關係,還有一個可能是 Timeout 的這個說明:
The Timeout applies to the entire request and response, not individually to the GetRequestStream and GetResponse method calls. 然而具體的還沒搞清楚,還需要去驗證。
後記
其實,設定這兩個屬性你可能只需要找到檔案,分分鐘就可以搞定,但是我為什麼會在這個過程遇到這些問題呢?一方面是對於C# 中網路請求的不熟悉,其次是找個時間,把以前的程式碼需要重構一下了,比如把HttpWebRequest
換成 HttpClient
等等。也讓我加深了對Http協議
的理解。
原文地址:https://www.cnblogs.com/xiyin/p/10548319.html