Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/288.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 暂停下载线程_C#_Multithreading_Suspend - Fatal编程技术网

C# 暂停下载线程

C# 暂停下载线程,c#,multithreading,suspend,C#,Multithreading,Suspend,我正在用c#编写一个非常简单的批量下载程序,它读取要下载的URL的.txt文件。我已经为它设置了一个全局线程和用于更新GUI的委托,按下“开始”按钮创建并启动该线程。我想做的是有一个“暂停”按钮,使我能够暂停下载,直到我点击“恢复”按钮。我该怎么做 有关守则: private Thread thr; private delegate void UpdateProgressCallback(int curFile); private void Begin_btn_Click(object sen

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

显然,我没有使用工人,我真的不希望使用工人,除非你能告诉我如何让它工作(我真的不理解工人)。如果您使用
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页面上的一些代码

您也可以将
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时添加事件。

我不是C#专家,但我相信这在很大程度上取决于您下载文件的方式。
Download()
中的实际代码是什么?您可能必须结束http连接并在恢复时重新建立它。否则TCP将超时。如果停止下载,则需要重新启动。您还需要跟踪停止的位置,可能需要下载并忽略这些部分,或者重新开始下载。我能看到这种工作的唯一方法是以帧形式下载;当你没有所有的帧时,你可以暂停下载或者继续下载下一帧。这基本上意味着您不会使用http。请不要建议其他人使用
Thread.Abort()
,除非完全必要。这种方法真的应该避免。我不知道还有什么其他方法可以满足海报的要求。我不知道有任何托管方式可以从web流(同步或其他方式)获取n个字节。如果我错了,请纠正我。你错了。您需要访问流,然后停止向下拉字节并随时停止/暂停读取是很简单的。Thread.Abort()几乎总是个坏主意。我检查了自己,发现
HttpWebResponse.GetResponseStream()
确实返回了一个流。我知道Thread.Abort()是个坏主意,只是找不到要读取的
流。我会修正我的答案。