3 votes

C# Task.WaitAll n'attend pas

Mon objectif est de télécharger des images à partir d'un seau Amazon Web Services.

J'ai la fonction de code suivante qui télécharge plusieurs images à la fois :

public static void DownloadFilesFromAWS(string bucketName, List<string> imageNames)
{
    int batchSize = 50;
    int maxDownloadMilliseconds = 10000;

    List<Task> tasks = new List<Task>();

    for (int i = 0; i < imageNames.Count; i++)
    {
        string imageName = imageNames[i];
        Task task = Task.Run(() => GetFile(bucketName, imageName));
        tasks.Add(task);
        if (tasks.Count > 0 && tasks.Count % batchSize == 0)
        {
            Task.WaitAll(tasks.ToArray(), maxDownloadMilliseconds);//wait to download
            tasks.Clear();
        }
    }

    //if there are any left, wait for them
    Task.WaitAll(tasks.ToArray(), maxDownloadMilliseconds);
}

private static void GetFile(string bucketName, string filename)
{
    try
    {
        using (AmazonS3Client awsClient = new AmazonS3Client(Amazon.RegionEndpoint.EUWest1))
        {
            string key = Path.GetFileName(filename);

            GetObjectRequest getObjectRequest = new GetObjectRequest() {
                 BucketName = bucketName,
                    Key = key
            };

            using (GetObjectResponse response = awsClient.GetObject(getObjectRequest))
            {
                string directory = Path.GetDirectoryName(filename);
                if (!Directory.Exists(directory))
                {
                    Directory.CreateDirectory(directory);
                }

                if (!File.Exists(filename))
                {
                    response.WriteResponseStreamToFile(filename);
                }
            }
        }
    }
    catch (AmazonS3Exception amazonS3Exception)
    {
        if (amazonS3Exception.ErrorCode == "NoSuchKey")
        {
            return;
        }
        if (amazonS3Exception.ErrorCode != null && (amazonS3Exception.ErrorCode.Equals("InvalidAccessKeyId") || amazonS3Exception.ErrorCode.Equals("InvalidSecurity")))
        {
            // Log AWS invalid credentials
            throw new ApplicationException("AWS Invalid Credentials");
        }
        else
        {
            // Log generic AWS exception
            throw new ApplicationException("AWS Exception: " + amazonS3Exception.Message);
        }
    }
    catch
    {
        //
    }
}

Le téléchargement des images fonctionne bien, mais l'application Task.WaitAll semble être ignoré et le reste du code continue à être exécuté - ce qui signifie que j'essaie de récupérer des fichiers qui n'existent pas actuellement (puisqu'ils n'ont pas encore été téléchargés).

J'ai trouvé ce réponse à une autre question qui semble être la même que la mienne. J'ai essayé d'utiliser la réponse pour modifier mon code mais il n'a toujours pas attendu que tous les fichiers soient téléchargés.

Quelqu'un peut-il me dire où je fais fausse route ?

6voto

NineBerry Points 923

Le code se comporte comme prévu. Task.WaitAll revient après dix secondes, même si tous les fichiers n'ont pas été téléchargés, car vous avez spécifié un délai d'attente de 10 secondes (10000 millisecondes) dans la variable maxDownloadMilliseconds .

Si vous voulez vraiment attendre que tous les téléchargements soient terminés, appelez Task.WaitAll sans spécifier de délai d'attente.

Utilisez

Task.WaitAll(tasks.ToArray());//wait to download

aux deux endroits.

Pour voir de bonnes explications sur la façon de mettre en œuvre des téléchargements parallèles tout en ne stressant pas le système (n'avoir qu'un nombre maximum de téléchargements parallèles), voir la réponse à l'adresse suivante Comment limiter Parallel.ForEach ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X