web-dev-qa-db-fra.com

Téléchargez plusieurs fichiers asynchrones et attendez qu'ils se terminent tous avant d'exécuter le reste du code

J'essaie de télécharger plusieurs fichiers sur Internet et j'attends qu'ils se terminent tous. Il s'agit d'une application console C # que j'exécute, donc aucun gestionnaire d'événements de barre de progression ne devrait être nécessaire. Cependant, il continue actuellement d'exécuter du code même si tous les fichiers n'ont pas été téléchargés.

  • 1.Télécharger tous les fichiers!
  • 2.Fichier de téléchargement terminé A
  • 3.Finished Téléchargement de tous les fichiers!
  • 4.Téléchargement du fichier B terminé
  • 5.Fichier de téléchargement C terminé

Comment attendriez-vous que tous les fichiers de téléchargement asynchrones soient terminés.

 private void DownloadMultipleFiles(List<DocumentObject> doclist)
    {
        foreach(var value in doclist){
            try
            {
                using (WebClient webClient = new WebClient())
                {
                    string downloadToDirectory = @Resources.defaultDirectory + value.docName;
                    webClient.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
                    webClient.DownloadFileCompleted += client_DownloadFileCompleted;
                    webClient.DownloadFileAsync(new Uri(value.docUrl), @downloadToDirectory);

                    //Add them to the local
                    Context.listOfLocalDirectories.Add(downloadToDirectory);
                }         
            }
            catch (Exception)
            {
                Errors.printError("Failed to download File: " + value.docName);
            }
        }
    }
21
user2100493

Les membres DownloadFileAsync/DownloadFileCompleted de WebClient utilisent le modèle asynchrone basé sur les événements . Si vous souhaitez utiliser async et await, vous devez utiliser Pattern asynchrone basé sur les tâches .

Dans ce cas, vous devez utiliser le membre DownloadFileTaskAsync , en tant que tel:

private async Task DownloadFileAsync(DocumentObject doc)
{
  try
  {
    using (WebClient webClient = new WebClient())
    {
      string downloadToDirectory = @Resources.defaultDirectory + doc.docName;
      webClient.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
      await webClient.DownloadFileTaskAsync(new Uri(doc.docUrl), @downloadToDirectory);

      //Add them to the local
      Context.listOfLocalDirectories.Add(downloadToDirectory);
    }         
  }
  catch (Exception)
  {
    Errors.printError("Failed to download File: " + doc.docName);
  }
}

private async Task DownloadMultipleFilesAsync(List<DocumentObject> doclist)
{
  await Task.WhenAll(doclist.Select(doc => DownloadFileAsync(doc)));
}

Veuillez noter que votre Context.listOfLocalDirectories.Add et Errors.printError les méthodes doivent être threadsafe.

45
Stephen Cleary