暂停下载线程

发布于 2024-11-29 23:28:51 字数 792 浏览 0 评论 0原文

我正在用 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)。任何帮助将不胜感激。

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?

The relevant code:

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
}

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

孤独患者 2024-12-06 23:28:51

如果您使用 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.GetResponse 中的一些代码MSDN 上的 页面。

您还可以更改 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);
            }

好处是您可以重新开始- 使用相同的线程。缺点是连接可能会超时并关闭。在后一种情况下,您需要检测到这一点并重新连接。

您可能还想添加下载完成时的事件。

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.

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

I used some code from HttpWebRequest.GetResponse page on MSDN.

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文