C#Task.WaitAll没有等待

时间:2016-05-16 09:49:49

标签: c# task

我的目标是从Amazon Web Services存储桶下载图像。

我有以下代码功能,可以一次下载多张图片:

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
    {
        //
    }
}

下载图像一切正常,但Task.WaitAll似乎被忽略了,其余代码继续执行 - 这意味着我试图获取当前不存在的文件(因为它们没有尚未下载)。

我找到this回答另一个似乎和我一样的问题。我尝试使用答案来更改我的代码,但它仍然不会等待下载所有文件。

谁能告诉我哪里出错了?

1 个答案:

答案 0 :(得分:6)

代码的行为与预期一致。即使没有下载所有文件,Task.WaitAll也会在十秒后返回,因为您已在变量maxDownloadMilliseconds中指定了超时10秒(10000毫秒)。

如果您确实要等待所有下载完成,请在不指定超时的情况下调用Task.WaitAll

使用

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

两地。

要查看有关如何在不强调系统的情况下实现并行下载的一些很好的解释(仅具有最大并行下载次数),请参阅How can I limit Parallel.ForEach?上的答案