2016-12-13 11 views
1

Я использую метод DownloadFileAsyncTask для загрузки файлов. Однако, когда я выполняю его в цикле, я получаю исключение, которое говорит мне, что параллельные операции не поддерживаются. Я попытался исправить это следующим образом:Как заставить WebClient ждать, пока предыдущая загрузка не будет завершена?

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 нить. Может быть, есть и другой способ сделать это?

+3

Почему вы выполняете множество загрузок в одно и то же время в первую очередь, если вы только когда-либо сделаете так, чтобы каждый из них подождал, пока никто не будет работать, прежде чем они действительно сделают свою работу? Если вы хотите загружать только по одному, то не начинайте больше одного раза за раз; только звезда следующая, когда предыдущий заканчивается. – Servy

+1

. Я не создаю новых клиентов на каждой итерации, потому что это накладные расходы. -> Это действительно накладные расходы? – MistyK

+0

@ Zbigniew Ну, это разница между выполнением различных загрузок параллельно и последовательно. Это значительно увеличит плотность сетевой нагрузки. Если вы действительно захотите (или сможете) выполнять параллельные операции, конечно, будет зависеть от ситуации. – Servy

ответ

2

Вам не хватает кода, необходимого для того, чтобы помочь вам, поэтому я написал этот быстрый пример, чтобы показать вам, что я думаю, что вы, возможно, захотите попробовать. Его в .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; 
} 
+1

Вы должны очень, очень редко использовать 'ContinueWith'. Вы почти всегда будете использовать 'await' за пределами очень редких ситуаций, когда вы действительно знаете, что делаете. – Servy

+0

@Servy Я обновил свой код, чтобы удалить ContinueWith. – Stephen

 Смежные вопросы

  • Нет связанных вопросов^_^