加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 使用WebClient下载多个文件时无限循环

发布时间:2020-12-16 00:07:02 所属栏目:百科 来源:网络整理
导读:概念:我正在制作一个从给定URL下载文件的C#应用??程序.文本框,添加的URL,文件下载,每个事件都以正确的方式发生. 我正在尝试重新创建此程序以逐个下载多个文件.我有一个带有一个url / line的文本框,解析正确,我将所有链接放在文本框中的字符串数组中.然后它
概念:我正在制作一个从给定URL下载文件的C#应用??程序.文本框,添加的URL,文件下载,每个事件都以正确的方式发生.

我正在尝试重新创建此程序以逐个下载多个文件.我有一个带有一个url / line的文本框,解析正确,我将所有链接放在文本框中的字符串数组中.然后它开始下载异步,我想让它一个一个地下载,所以我在foreach循环中进行了一个while循环,因为我不想在下一个url之前直到当前的下载完成.

问题是:我进入一个无限循环(虽然我之前做了这个工作(idk如何),如果我在while循环中放置了一个消息框(注意:我在一分钟前重试过,这次没有做到这一点) ).

我只是展示代码片段:

foreach (string url in urllist)
{
    isdonwloaded = false;
    string filename = url.Split('/').Last();
    label3.Text = filename;
    webclient.DownloadFileAsync(new Uri(url),@"C:UsersKrisz" + @"" + filename);

    while (!isdonwloaded) // this was the first idea,but with webclient.IsBusy it did the same thing
    {
        // MessageBox.Show(counter);
        Thread.Sleep(1000);
        label8.Text = "Download in progress...";
    }

    counter++;
    label8.Text = "Done!";
}

// Events:
webclient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(webc_DownloadProgressChanged);
webclient.DownloadFileCompleted += new AsyncCompletedEventHandler(webc_DownloadFileCompleted);

// The DownloadFileCompleted event:
void webc_DownloadFileCompleted(object sender,AsyncCompletedEventArgs e)
{
    label7.Text = String.Format("Files {0} / {1}",counter,arraylength(urllist));
    isdonwloaded = true;
}

我已经调查过这个帖子:WebClient.DownloadFileAsync – Download files one at a time,但我无法让它以这种方式工作. (也许我误会了什么?)

有人可以给我一些提示吗,我做错了什么?我从来没有真正使用过事件,因此遇到错误只是时间问题.
每一点帮助都是非常有用的,这个程序对我来说很有用.

解决方法

好的,首先,了解您的代码现在无法正常工作的原因.

想象一下,你在办公室里有两个人.两者都有“在盒子里”.他们的工作流程是:他们检查他们的收件箱.如果收件箱中有任务,则他们执行任务直到完成,然后再次检查他们的收件箱,重复.

Worker 1在收件箱中收到一条消息,说明您的下一个任务是:

>关闭开关
>将标签更改为“下载”
>告诉工人2下载文件
>检查开关是否打开 – 如果它是断开的话;如果没有,那就去睡一秒钟.
>回到上一步
>将标签更改为“完成”
>此任务现已完成

工作人员1关闭开关并将以下任务放入工作人员2的收件箱中:

>下载文件
>告诉工人1打开开关
>这个任务完成了

然后,工人1检查开关是否打开.它不是,所以工人1去睡觉.

Worker 2下载文件,然后在worker 1的收件箱中发送一条消息,说明:

>打开开关
>这个任务完成了

现在你明白为什么工人1会永远睡觉,对吧?该开关永远不会被翻转,因为翻转该开关是工人1的工作,而工作人员1正在睡觉直到它被翻转.在当前任务完成之前,工作人员1不会查看其收件箱,并且当切换该开关之前,当前任务不会完成.

这给了我们一个解决方案的想法,但它不是一个好的解决方案.

解决这个问题的廉价,肮脏,危险和不明智的方法是使用“DoEvents”而不是“Sleep”.这将任务更改为:

>关闭开关
>将标签更改为“下载”
>告诉工人2下载文件
>检查开关是否打开 – 如果它是断开的话;如果没有,请检查您的收件箱中的邮件,并执行您在那里找到的任何内容.
>回到上一步
>将标签更改为“完成”
>这个任务完成了

这解决了您的直接问题,但它引入了新问题.我们现在不再拥有干净的工作流程;一个收件箱任务可以生成第二个收件箱任务,这可以反过来产生第三个收件箱任务.任务可以变得“重入”,其中一个任务最终会启动自身的第二个版本.这种解决方案不够优雅,适用于难以调试的情况.理想情况下,您希望收件箱任务具有在旧的任务完成后启动新任务的属性,而不是旧的任务仍有工作要做.

对你的问题(如果你使用C#5)更好的廉价和肮脏的修复是使用

await Task.Delay(1000);

而不是睡眠或DoEvents.这对工作流程进行了微妙的改变.基本上它变成:

>关闭开关
>将标签更改为“下载”
>告诉工人2下载文件
>检查开关是否打开
>如果它打开然后将标签更改为“完成”;这个任务完成了.
>如果没有,那么请工人3在一秒钟内给我发一项任务;这个任务完成了.

如果告诉worker 3向worker 1发送一个新任务,那么它发送的新任务是:

>检查开关是否打开
>如果它打开然后将标签更改为“完成”;这个任务完成了.
>如果没有,那么请工人3在一秒钟内给我发一项任务;这个任务完成了.

你看到如何巧妙但正确地改变工作流程?现在,worker 1将标签更改为下载,向worker 2发送消息,检查交换机,向worker 3发送消息,然后返回其收件箱. Worker 2执行下载并向worker发送消息1. Worker 1翻转开关并返回收件箱.工作人员3向工作人员发送消息1.工作人员1检查交换机,将标签更改为完成,然后返回收件箱.

现在没有任务告诉您在收件箱中查看更多任务.每个收件箱任务按顺序处理:后到达的任务总是在较早到达的任务完成后启动.

然而,最好的解决方案是拥有一个版本的DownloadClientAsync,它本身可以返回一个可以等待的任务.不幸的是,这是无效的.构建一个特殊版本的DownloadClientAsync,它返回一个可以等待的任务,留作练习.一旦你有了这样一个帮助方法,那么代码变得微不足道;你等待那个任务.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读