暂停下载线程 [英] Pausing a download thread

查看:122
本文介绍了暂停下载线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用c#编写一个非常简单的批量下载程序,该程序读取URL的.txt文件进行下载.我已经使用全局线程和委托对其进行了设置,以更新GUI,按下开始"按钮将创建并启动该线程.我想要做的是有一个暂停"按钮,使我可以暂停下载,直到我点击恢复"按钮.我该怎么做?

I'm writing a very simple bulk download program in c# that reads a .txt file of URLs to download. I've set it up with a global Thread and delegate for updating the GUI, and the pressing of the "Begin" button creates and starts that thread. What I want to do is have a "Pause" button that enables me to pause the download until I hit the "Resume" button. How do I do this?

相关代码:

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).任何帮助将不胜感激.

Obviously, I am NOT using a Worker, and I really don't wish to unless you can show me how to get it to work (I don't really understand workers). Any help would be appreciated.

推荐答案

如果使用System.Net.WebClient.DownloadFile()System.Net.WebClient.DownloadFileAsync()方法,则无法暂停下载.这些方法之间的区别在于,后一种方法将启动异步下载,因此,如果您使用此方法,则无需自己创建单独的线程.不幸的是,使用任何一种方法执行的下载都无法暂停或恢复.

If you use System.Net.WebClient.DownloadFile() or System.Net.WebClient.DownloadFileAsync() method then you cannot pause the download. The difference between these methods is that the latter method will start an asynchronous download so you will not need to create a separate thread yourself if you use this method. Unfortunately, downloads executed with either method cannot be paused or resumed.

您需要使用System.Net.HttpWebRequest.尝试这样的事情:

You need to use System.Net.HttpWebRequest. Try something like this:

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.GetResponse 页面.

除了在Pause上停止线程并在Resume上启动新线程之外,您还可以更改while循环以等待直到恢复下载,如下所示:

Instead of stopping the thread on Pause and starting a new one on Resume, you can also change the while loop to wait until download is resumed as following:

            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);
            }

有利的一面是,您可以重新使用同一线程.不利的一面是连接可能会超时并关闭.在后一种情况下,您将需要检测并重新连接.

The up-side is that you may be able to re-use the same thread. The down-side is that the connection may timeout and become closed. In the latter case, you will need to detect this and re-connect.

您可能还想为下载完成时添加一个事件.

You may also want to add an event for when the donwload is completed.

这篇关于暂停下载线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆