2011-08-14 165 views
3

我在c#中編寫了一個非常簡單的批量下載程序,該程序讀取要下載的URL的.txt文件。我已經用全局線程和代理來設置它來更新GUI,並且按下「開始」按鈕將創建並啓動該線程。我想要做的是有一個「暫停」按鈕,使我可以暫停下載,直到我點擊「恢復」按鈕。我該怎麼做呢?暫停下載線程

相關的代碼:

private Thread thr; 
private delegate void UpdateProgressCallback(int curFile); 

private void Begin_btn_Click(object sender, EventArgs e) 
{ 
    thr = new Thread(Download); 
    thr.Start(); 
} 

private void Pause_btn_Click(object sender, EventArgs e) 
{ 
    Pause_btn.Visible = false; 
    Resume_btn.Visible = true; 
    //{PAUSE THREAD thr} 
} 

private void Resume_btn_Click(object sender, Eventargs e) 
{ 
    Pause_btn.Visible = true; 
    Resume_btn.Visible = false; 
    //{RESUME THREAD thr} 
} 

public void Download() 
{ 
    //Download code goes here 
} 

很顯然,我不使用工人,我真的不希望,除非你能告訴我怎麼得到它的工作(我真的不明白工人)。任何幫助,將不勝感激。

+2

我不是C#專家,但我相信這將*非常*取決於您如何下載文件。 'Download()'中的實際代碼是什麼? – jtbandes

+4

你可能不得不結束http連接並在簡歷上重新建立它。否則TCP將超時。 – sleeplessnerd

+1

如果您停止下載,則需要重新啓動,您還需要跟蹤停止的位置,並可能下載並忽略這些部分,或重新開始下載。 –

回答

2

如果您使用System.Net.WebClient.DownloadFile()System.Net.WebClient.DownloadFileAsync()方法那麼您不能暫停下載。這些方法之間的區別在於後一種方法將啓動異步下載,因此如果使用此方法,則不需要自己創建單獨的線程。不幸的是,使用這兩種方法執行的下載無法暫停或恢復。您需要使用System.Net.HttpWebRequest。嘗試這樣的事情:

class Downloader 
{ 
    private const int chunkSize = 1024; 
    private bool doDownload = true; 

    private string url; 
    private string filename; 

    private Thread downloadThread; 

    public long FileSize 
    { 
     get; 
     private set; 
    } 
    public long Progress 
    { 
     get; 
     private set; 
    } 

    public Downloader(string Url, string Filename) 
    { 
     this.url = Url; 
     this.filename = Filename; 
    } 

    public void StartDownload() 
    { 
     Progress = 0; 
     FileSize = 0; 
     commenceDownload(); 
    } 

    public void PauseDownload() 
    { 
     doDownload = false; 
     downloadThread.Join(); 
    } 

    public void ResumeDownload() 
    { 
     doDownload = true; 
     commenceDownload(); 
    } 

    private void commenceDownload() 
    { 
     downloadThread = new Thread(downloadWorker); 
     downloadThread.Start(); 
    } 

    public void downloadWorker() 
    { 
     // Creates an HttpWebRequest with the specified URL. 
     HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create(url); 

     FileMode filemode; 
     // For download resume 
     if (Progress == 0) 
     { 
      filemode = FileMode.CreateNew; 
     } 
     else 
     { 
      filemode = FileMode.Append; 
      myHttpWebRequest.AddRange(Progress); 
     } 

     // Set up a filestream to write the file 
     // Sends the HttpWebRequest and waits for the response.   
     using (FileStream fs = new FileStream(filename, filemode)) 
     using (HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse()) 
     { 
      // Gets the stream associated with the response. 
      Stream receiveStream = myHttpWebResponse.GetResponseStream(); 

      FileSize = myHttpWebResponse.ContentLength; 

      byte[] read = new byte[chunkSize]; 
      int count; 


      while ((count = receiveStream.Read(read, 0, chunkSize)) > 0 && doDownload) 
      { 
       fs.Write(read, 0, count); 
       count = receiveStream.Read(read, 0, chunkSize); 

       Progress += count; 
      } 
     } 
    } 
} 

我在MSDN上使用了HttpWebRequest.GetResponse頁面的一些代碼。

而是停在暫停線程,並開始對恢復一個新的,你也可以改變while循環要等到下載恢復如下:

  while ((count = receiveStream.Read(read, 0, chunkSize)) > 0) 
      { 
       fs.Write(read, 0, count); 
       count = receiveStream.Read(read, 0, chunkSize); 

       Progress += count; 

       while(!doDownload) 
        System.Threading.Thread.Sleep(100); 
      } 

的上側是,你可能能夠重新使用相同的線程。不利的一面是連接可能會超時並關閉。在後一種情況下,您需要檢測並重新連接。

您可能還想爲donwload完成時添加事件。

+1

請不要建議其他人使用'Thread.Abort()',除非完全有必要。應該真的避免這種方法。 – svick

+0

我不知道有任何其他方式去做海報想要的東西。我不知道任何從Web流獲取_n_個字節的管理方式(同步或其他方式)。如果我錯了,請糾正我。 – Serge

+1

你錯了。你需要訪問* stream *,那麼在任何時候停止下拉字節並停止/暫停讀取都是微不足道的。 Thread.Abort()幾乎總是一個*不好的想法。 –