2011-08-14 125 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()几乎总是一个*不好的想法。 –