2014年5月30日 星期五

[C#] 解決HttpWebResponse.GetResponseStream().close()執行很慢的問題



一年多前我寫了個下載網頁上檔案的app,例如下載一個"http://this.is.a.file.mp4"的檔案。


想當然會碰上使用者要中斷下載作業的需求,但寫出來的成品總是不夠完美,一開始的程式碼片段如下:


HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://this.is.a.file.mp4");
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();                        
Stream dataStream = resp.GetResponseStream();
FileStream fs= new FileStram(DOWNLOAD_FILE_PATH, FileMode.Create, FileAccess.Write);
int size =0;
byte[] buffer = new byte[8192];

do
{
    if(user_interrupt)
    {
        fs.close();
        resp.close();
        dataStream.close();
        break;
    }
    
    size = dataStream.Read(buffer, 0, buffer.Length);
    if (size > 0)
    {
        fs.Write(buffer, 0, size);
    }
}
while(size>0);

跑了幾次除錯後,發現要中斷時,在resp.close()dataStream.close()都會卡很久,五到十分鐘不等

當時找答案時找錯方向,也不知道該怎麼描述問題,只好先閒置著。

一年多以後回過頭來做code review,才發現是忽略了很重要的基本原則 「每個開始都要有個結束」。

首先,關閉下載檔案的資料寫入fs.close()
接著把對URLrequest關掉,在fs.close()後加入這行"rep.Abort();"
再來就可以把respdataStream都順利關掉



再次叮嚀自己,每個開始,最好都要有個結束。

完成的sample如下

HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://this.is.a.file.mp4");
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();                        
Stream dataStream = resp.GetResponseStream();
FileStream fs= new FileStram(DOWNLOAD_FILE_PATH, FileMode.Create, FileAccess.Write);
int size =0;
byte[] buffer = new byte[8192];

do
{
    if(user_interrupt)
    {
        fs.close();
        req.Abort();
        resp.close();
        dataStream.close();
        break;
    }
    
    size = dataStream.Read(buffer, 0, buffer.Length);
    if (size > 0)
    {
        fs.Write(buffer, 0, size);
    }
}
while(size>0);


沒有留言:

張貼留言