如何使WebClient等到上一次下载完成



我正在使用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线程。也许还有其他方法可以这样做?

您错过了很多可以帮助您的代码,因此我写了这个快速示例,以向您展示我想尝试的东西。它在.net核心中,但本质上是相同的,只需将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;
}