【问题标题】:How to make WebClient wait until previous download is finished?如何让 WebClient 等到之前的下载完成?
【发布时间】:2016-12-13 20:52:05
【问题描述】:

我正在使用DownloadFileAsyncTask 方法下载文件。但是,当我在循环中执行它时,我得到一个异常,它告诉我不支持并发操作。我试着像这样修复它:

  public async Task<string> Download(string uri, string path)
    {
        if (uri == null) return;

        //manually wait for previous task to complete
        while (Client.IsBusy)
        {
            await Task.Delay(10);
        }

        await Client.DownloadFileTaskAsync(new Uri(absoluteUri), path);

        return path;
    }

有时它会起作用,当迭代次数不大(1-5)时,当它运行 10 次或更多次时,我会收到此错误。 Client 这是WebClient,我创建了一次。我不会在每次迭代中产生一个新的客户端,因为它会产生开销。 回到我说的,如何让WebClient 在之前的下载完成之前等待?这里还有一个问题是为什么IsBusy 适用于少量下载。 我正在使用的代码:

 public IEnumerable<Task<string>> GetPathById(IEnumerable<Photo> photos)
    {
        return photos?.Select(
                     async photo =>
                     {
                         var path = await Download(Uri, Path);
                         return path;
                     });
    }

我想下载很多文件并且不要阻塞我的 Ui 线程。也许还有其他方法可以做到这一点?

【问题讨论】:

  • 如果您只想让每个人都等到没有其他人在工作,然后他们才真正开始工作,为什么还要同时执行大量下载?如果您只想一次下载一个,则不要一次启动多个;只有在前一个完成后才为下一个加注星标。
  • 。我不会在每次迭代中产生一个新的客户端,因为它会产生开销。 -> 真的是开销吗?
  • @Zbigniew 好吧,这就是并行执行各种下载与按顺序执行各种下载之间的区别。这将大大增加网络负载的密度。您是否真的想要(或能够)并行执行这些操作当然取决于具体情况。
  • 是的,我不创建新实例的原因是速度较慢。

标签: c# async-await task webclient


【解决方案1】:

您缺少很多帮助您解决问题所需的代码,因此我编写了这个快速示例来向您展示我认为您可能想要尝试的内容。它在 .NET Core 中,但本质上是相同的,只是将 HttpClient 替换为 WebClient。

    static void Main(string[] args)
{
    Task.Run(async () =>
    {
        var toDownload = new string[] { "http://google.com", "http://microsoft.com", "http://apple.com" };
        var client = new HttpClient();

        var downloadedItems = await DownloadItems(client, toDownload);

        Console.WriteLine("This is async");

        foreach (var item in downloadedItems)
        {
            Console.WriteLine(item);
        }

        Console.ReadLine();
    }).Wait();
}

static async Task<IEnumerable<string>> DownloadItems(HttpClient client, string[] uris)
{
    // This sets up each page to be downloaded using the same HttpClient.
    var items = new List<string>(); 
    foreach (var uri in uris)
    {
        var item = await Download(client, uri);
        items.Add(item);
    }
    return items;
}

static async Task<string> Download(HttpClient client, string uri)
{
    // This download the page and returns the content.
    if (string.IsNullOrEmpty(uri)) return null;

    var content = await client.GetStringAsync(uri);
    return content;
}

【讨论】:

  • 你应该非常非常少使用ContinueWith。你应该几乎总是使用await,除非你真的知道你在做什么。
猜你喜欢
  • 1970-01-01
  • 2023-03-10
  • 1970-01-01
  • 2011-04-14
  • 1970-01-01
  • 1970-01-01
  • 2020-05-26
  • 2010-12-05
  • 2022-09-25
相关资源
最近更新 更多