因為有些人可能會疑惑,將了這麼多多線程,到底在實際的應用上有什麼作用的呢? 這裡我在這裡用多線程簡單實現了一個檔案的下載的功能。
伺服器端頁面:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="FileServer.Default" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"> <title></title></head><body> <form id="form1" runat="server"> <div> <asp:Image ID="Image1" runat="server" ImageUrl="~/Images/1.gif" /> 說明: CLR Via C# </div> </form></body></html>
伺服器頁面只是一個簡單顯示需要下載檔案的一些資訊,這裡通過Handler.ashx來處理檔案的下載,把檔案的轉化為二進位位元組寫入到輸出資料流中,具體實現代碼為:
public void DownLoad(object state) { // 計時對象 Stopwatch sw = Stopwatch.StartNew(); HttpWebRequest request; HttpWebResponse response; Stream stream; // 下載下來的儲存的地址 string savepath = "D:\\Download.pdf"; FileStream savestream = new FileStream(savepath, FileMode.OpenOrCreate); try { // 發出請求 request = (HttpWebRequest)HttpWebRequest.Create(url); // 獲得回應對象 response = (HttpWebResponse)request.GetResponse(); // 獲得回應流 stream = response.GetResponseStream(); byte[] bytes = new byte[10240]; int readsize; // 每次都讀取10240位元組 // 採用的是同步讀取方法 // 計算耗費的時間 readsize = stream.Read(bytes, 0, bytes.Length); while (readsize > 0) { savestream.Write(bytes, 0, readsize); readsize = stream.Read(bytes, 0, bytes.Length); } sw.Stop(); MessageBox.Show("下載耗時為:" + sw.Elapsed.ToString(), "提示"); } catch (Exception ex) { MessageBox.Show(ex.Message, "Error"); } finally { savestream.Close(); } }
這樣就利用線程池線程簡單完成了用戶端下載伺服器端檔案的功能,並且使用線程池線程這樣不會主線程,從而導致在下載檔案時,介面同樣可以操作,如果不採用多線程操作的話將會在下載過程導致介面“卡死”現象,這樣就會給使用者帶來不好的使用者體驗。
其實本來還想做複雜點的, 開始想實現的功能,是伺服器端斷點續傳,然後用戶端多線程下載的功能的,這個樣本中只用到了一個線程池線程來完成下載任務,本來想通過執行多個線程池線程來完成下載任務的, 每個線程只負責一部分的讀取工作, 然後把每個線程中讀取的位元組合并起來就是完整的檔案位元組了,但是這裡遇到一個問題,怎麼在伺服器端實現續傳的功能的, 用戶端通過AddRange方法來發出部分讀取請求,然後伺服器端就要對要求標頭Range進行解析的,實現原理我還是清楚,但是在做的過程中還是出現了問題。所以這裡只能分享一個簡單的下載檔案的功能給大家了, 至於多線程的下載和斷點續傳和大檔案的上傳等問題,等我學習了再和大家分享, 如果有大牛可以協助我解決服務端斷點續傳的問題的話,歡迎留言。
源檔案下載連結: http://files.cnblogs.com/zhili/FileServer.zip (下載下來後只需要在伺服器端Resources檔案夾下添加一個檔案就可以運行了)