CODE-關於Response.Flush的小小測試
7 |
同事要用網頁跑一段很久的程序,因此想用"簡便"的方法產生即時狀態更新的效果,以免使用者等到抓狂。(簡便->代表用最少的Code做出需要的功能,有沒有用到又酷又炫的AJAX,架構、程式漂亮與否是其次)
我想到最簡單的方法是在這段要執行很久的ASP.NET中,用Response.BufferOutput = false加上Response.Write("..")、Response.Flush(),每執行到一個段落,輸出一部分內容來更新狀態。
於是我寫了以下的Sample Code:
<%@ Page Language="C#" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
Response.BufferOutput = false;
Response.Flush();
for (int i = 1; i < 10; i++)
{
Response.Write("<li>" + i.ToString());
Response.Flush();
System.Threading.Thread.Sleep(1000);
}
Response.Write("</body></html>");
Response.End();
}
</script>
<html">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
</form>
</body>
</html>
在我的機器上測試成功後,丟給同事測試,傳來結果卻是最後才一次輸出所有數字。
自己將程式放到不同機器反覆測試了一下,發現有趣的現象: 這段程式有時可以陸續印出1, 2, 3, 4、有時則會等到最後才一次印出。而且往往第一次執行不OK,但按下IE的重新載入卻又成功。
會不會問題出在瀏覽器端?
於是我用HttpWatch進行觀察,驗證了我的猜測,在成功與失敗兩種情況中,資料都有陸續送至瀏覽器,但卻分別得到陸續印出或一次印出兩種結果。
我又另外試了Firefox及Chrome,得到更有趣的結果: Firefox永遠陸續印出,Chrome則永遠一次印出。
我大膽推論,當收到的HTML碼還不完整時,要不要Render出元素出來,取決於Browser。Firefox選擇了收到立即處理,Chrome則是等收齊再說。而IE最彈性,當發現接收資料的速率較慢時,怕會收到太多破碎不完整的HTML片段做白工,選擇收集齊再產出;當接收速度不差時,就採行收到立即處理。這個推論可以解釋,為何在本機總是成功,在遠端第一次失敗,Reload會成功,但是否為真我就不敢確定了。
當HTML不完整時,各瀏覽器的處理原則不一,看來這個方法並不理想。我想到另一招,<script>中的段落應該都會即時處理才對,所以將程式修改如下:
<%@ Page Language="C#" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
Response.BufferOutput = false;
Response.Clear();
Response.Write("<html><body><span id='spnDisp'></span>");
Response.Flush();
for (int i = 1; i < 10; i++)
{
Response.Write("<script type='text/javascript'>");
Response.Write("document.getElementById('spnDisp').innerHTML='"
+ i.ToString() + "';");
Response.Write("</" + "script>");
Response.Flush();
System.Threading.Thread.Sleep(1000);
}
Response.Write("</body></html>");
Response.End();
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
</form>
</body>
</html>
Bingo!! 使用IE, Firefox, Chrome測試都可成功運作! 不過我還是不確定,會不會在某些特例下失常? 大家看看還有沒有什麼點子,歡迎討論。
Comments
# by 讚啊!
不錯,很好的東西!
# by Will 保哥
這一行有讓我會心一笑: Response.Write("</" + "script>"); P.S. 這是 ASP.NET 的 Behind 喔! ^_^
# by Jeffrey
to Will, 經驗裡放在Inline Code時會有這個問題,如果寫在Code Behind的cs中就沒這個顧忌。巧得很,才讀到一篇相關文章沒幾小時(http://www.dotblogs.com.tw/yilinliu/archive/2008/08/14/4909.aspx ),馬上就給我來個臨時抽考。
# by Johnny
如果使用 Response.Write 輸出 JavaScript 的話, 如果網頁中有使用 UpdatePanel, 我記得是會發生問題。
# by Martin
請問一下, 這個效果在UpdatePanel中要怎麼樣才能做到呢?
# by Jeffrey
to Martin, 如果是UpdatePanel,應該做法會很不相同,我的想法是分成兩個網頁,一個用來跑程式,一個則用來看進度。跑程式時要定期將狀態更新在Server端的Session或Cache,進度程式就可以用定期觸發UpdatePanel的方式讀到最近的進度。大概的會從這個方向去研究,但似乎稍有難度就是了。
# by 貓霸
真是難以為情,今天才發生RESPONSE.BINARYWRITE的狀況,因為過年前換了台全SSD網頁+MSSQL伺服器,一個輸出EXCEL的頁面出了問題,上估狗搜到這裡,加了一句Thread.Sleep(1000);,搞定! 看來伺服器跑太快也會有問題,尷尬