暂停下载线程

本文关键字:线程 下载 暂停 | 更新日期: 2023-09-27 18:05:28

我正在用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
}

显然,我没有使用Worker,而且我真的不希望使用,除非你能告诉我如何让它工作(我真的不懂Worker)。

暂停下载线程

如果您使用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;
            }
        }
    }
}

我使用了一些代码从HttpWebRequest。MSDN上的GetResponse页面。

与其在Pause时停止线程,在Resume时启动一个新的线程,还可以更改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);
            }

这样做的好处是可以重用同一个线程。缺点是连接可能超时并关闭。在后一种情况下,您需要检测并重新连接。

你可能还想添加一个事件当下载完成