公司[1]一牛人看我的程式碼,說我設定的timeout有誤,還應該設定ReadWriteTimeout。本人很不服,於是上網檢視了相關說明。
MSDN對ReadWriteTimeout的說明如下:
在寫入由 GetRequestStream 方法返回的流時,或在讀取由 GetResponseStream 方法返回的流時,會用到 ReadWriteTimeout 屬性。
具體而言,ReadWriteTimeout 屬性控制 Read 方法(用來讀取由 GetResponseStream 方法返回的流)和 Write 方法(用來寫入由 GetRequestStream 方法返回的流)的超時。
若要指定等待請求完成的時間量,請使用 Timeout 屬性[2]。
MSDN對Timeout的說明如下:
Timeout 是進行後續同步請求時使用 GetResponse 方法等待響應以及 GetRequestStream 方法等待流所允許的毫秒數。 Timeout 適用於整個請求和響應,不單獨對GetRequestStream 與 GetResponse 方法呼叫響應。 如果資源在超時期限內未返回,請求將引發 WebException,並將 Status 屬性設定為 WebExceptionStatus.Timeout。
Timeout 屬性必須在 GetRequestStream 或 GetResponse 方法被呼叫之前設定。 在呼叫 GetRequestStream 或 GetResponse 方法之後更改 Timeout 屬性不起任何作用
Timeout 屬性對使用 BeginGetResponse 或 BeginGetRequestStream 方法生成的非同步請求無效[3]。
通俗一點說,Timeout設定的是從發出請求開始算起,到與伺服器建立連線的時間。ReadWriteTimeout設定的是從建立連線開始,到下載資料完畢所歷經的時間。
以下一個例子可以說明這個問題[4]。
首先是抓取的程式碼:
1
2
3
4
5
6
7
8
9
|
HttpWebRequest req =(HttpWebRequest)WebRequest.Create( "http://www.kangry.net/t1" ); req.Timeout = 5000; //設定超時時間為5秒 Stopwatch timer = new Stopwatch(); timer.Start(); HttpWebResponse resp = (HttpWebResponse)req.GetResponse(); StreamReader reader = new StreamReader(resp.GetResponseStream()); string data = reader.ReadToEnd(); timer.Stop(); textBox1.AppendText(data + "\r\n" +timer.Elapsed.TotalSeconds.ToString()+ "\r\n" ); |
其中我做了幾個頁面,分別是”t1″、“t2”、“t3”、“t4”。
其中t1頁面直接返回文字內容,用作基礎對照。
t2頁面設定了一個延時,但是延時時間在超時的範圍內。
t3頁面設定了一個延時,但是延時時間超過抓取程式的timeout時間。
t4頁面首先是先往客戶端傳送一部分內容,然後延時一段比timeout更長的時間,模擬出網速很慢的樣子,再把剩下的字串傳送完畢。
程式碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
public ActionResult t1() { return Content( "直接返回內容。" ); } public ActionResult t2() { System.Threading.Thread.Sleep(3000); return Content( "休息了3秒" ); } public ActionResult t3() { System.Threading.Thread.Sleep(7000); return Content( "休息了7秒" ); } public ActionResult t4() { //這個是虛擬碼,實際使用的是 t4.aspx 寫的,不是asp.net mvc Response.Write( "hello" ); Response.Flush(); System.Threading.Thread.Sleep(8000); return Content( " Kangry" ); } |
測試的結果是:
t1很快返回內容,且沒有錯誤。
t2在3秒後也返回了內容,且沒有錯誤。
t3在5秒後客戶端丟擲timeout的錯誤。
t4在8秒後返回內容,並沒有出現錯誤。
根據測試結果,timeout設定的時間並不包括資料下載所耗費的時間。