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

时间:2010-01-11 14:00:57

标签: c# asp.net multithreading webclient download

我正在使用以下代码从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);
}

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

有人可能会问:“你为什么不使用同步的DownloadFile方法?”因为:

  1. 我想利用DownloadFileAsync提供的事件。
  2. 我不想创建Webclient的多个实例以避免泛滥服务器。
  3. 这是我想到的解决方案:

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

    但是,这种方法存在一些问题:

    1. Thread.Sleep()正在锁定我的表单。我仍然需要创建自己的Thread或使用BackgroundWorker。 (我想尽可能避免这种情况)
    2. 在下载所有文件后,将触发DownloadFileCompleted事件。我不知道这是否是使用System.Threading.Thread.Sleep(1000);
    3. 的副作用

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

      谢谢!

3 个答案:

答案 0 :(得分:8)

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

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

其中列表是类型为列表&lt;附件&gt; 的私有字段。 在此之后,您应该配置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);
}

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

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

答案 1 :(得分:2)

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

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

其中clientWebClient对象的实例。

答案 2 :(得分:0)

我认为应该使用Queue