C# WebClient.DownloadFileAsync - 一次下载一个文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2042258/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 22:56:15  来源:igfitidea点击:

WebClient.DownloadFileAsync - Download files one at a time

c#asp.netmultithreadingwebclientdownload

提问by Ian

I am using the code below to download multiple attachments from a TFS server:

我正在使用下面的代码从 TFS 服务器下载多个附件:

foreach (Attachment a in wi.Attachments)
{    
    WebClient wc = new WebClient();
    wc.Credentials = (ICredentials)netCred;
    wc.DownloadFileCompleted += new AsyncCompletedEventHandler(wc_DownloadFileCompleted);
    wc.DownloadFileAsync(a.Uri, "C:\" + a.Name);
}

I would like to download multiple files using DownloadFileAsync, but I want them to be downloaded one by one.

我想使用 DownloadFileAsync 下载多个文件,但我希望它们被一个一个地下载。

One may ask "Why don't you just use the synchronous DownloadFile method?" Its because:

有人可能会问“为什么不直接使用同步 DownloadFile 方法?” 这是因为:

  1. I want to make use of the events provided by DownloadFileAsync.
  2. I don't want to make multiple instances of the Webclient to avoid flooding the server.
  1. 我想利用 DownloadFileAsync 提供的事件。
  2. 我不想创建多个 Webclient 实例以避免淹没服务器。

This is the solution that I thought of:

这是我想到的解决方案:

foreach (Attachment a in wi.Attachments)
{        
    WebClient wc = new WebClient();
    wc.Credentials = (ICredentials)netCred;
    wc.DownloadFileCompleted += new AsyncCompletedEventHandler(wc_DownloadFileCompleted);
    wc.DownloadFileAsync(a.Uri, "C:\" + a.Name);
    while (wc.IsBusy)
    {
        System.Threading.Thread.Sleep(1000);
    }
}

However, there are a couple of problems with this approach:

但是,这种方法有几个问题:

  1. The Thread.Sleep() is locking up my Form. I still need to make my own Thread or use BackgroundWorker. (I would like to avoid this as much as possible)
  2. The DownloadFileCompleted event is being triggered after ALLfiles has been downloaded. I don't know if this is a side-effect of using System.Threading.Thread.Sleep(1000);
  1. Thread.Sleep() 正在锁定我的表单。我仍然需要创建自己的线程或使用BackgroundWorker。(我想尽可能避免这种情况)
  2. 下载所有文件后触发 DownloadFileCompleted 事件。我不知道这是否是使用 System.Threading.Thread.Sleep(1000) 的副作用;

Is there a better approach to download files one at a time using WebClient.DownloadFileAsync?

是否有更好的方法使用 WebClient.DownloadFileAsync 一次下载一个文件?

Thanks!

谢谢!

采纳答案by Andrey Shvydky

To simplify the task you can create separated attachment list:

为了简化任务,您可以创建单独的附件列表:

list = new List<Attachment>(wi.Attachments);

where listis private field with type List<Attachment>. After this you should configure WebClient and start downloading of first file:

其中list是类型为List<Attachment> 的私有字段。在此之后,您应该配置 WebClient 并开始下载第一个文件:

if (list.Count > 0) {
   WebClient wc = new WebClient();
   wc.Credentials = (ICredentials)netCred;
   wc.DownloadFileCompleted += new AsyncCompletedEventHandler(wc_DownloadFileCompleted);
   wc.DownloadFileAsync(list[0].Uri, @"C:\" + list[0].Name);
}

Your DownloadFileComplete handler should check if not all files already downloaded and call DownloadFileAsync again:

您的 DownloadFileComplete 处理程序应检查是否所有文件都已下载并再次调用 DownloadFileAsync:

void wc_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e) {
   // ... do something useful 
   list.RemoveAt(0);
   if (list.Count > 0)
      wc.DownloadFileAsync(list[0].Uri, @"C:\" + list[0].Name);
}

This code is not optimized solution. This is just idea.

此代码不是优化的解决方案。这只是想法。

回答by heavenwing

I think that should use Queue

我认为应该使用 Queue

回答by user2667898

At the risk of sounding like an idiot, this worked for me:

冒着听起来像个白痴的风险,这对我有用:

Console.WriteLine("Downloading...");
client.DownloadFileAsync(new Uri(file.Value), filePath);
while (client.IsBusy)
{
    // run some stuff like checking download progress etc
}
Console.WriteLine("Done. {0}", filePath);

Where clientis an instance of a WebClientobject.

对象client的实例在哪里WebClient