C#Task.WaitAll未在等待
问题描述:
我的目标是从亚马逊网络服务存储桶下载图像。C#Task.WaitAll未在等待
我有以下的代码功能,一次下载多张图片:
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答案似乎与我的另一个问题。我试图使用答案来更改我的代码,但它仍然不会等待所有文件被下载。
谁能告诉我我哪里出错了吗?
答
该代码的行为如预期。即使并非所有文件都已下载,在十秒后仍会返回Task.WaitAll
,因为您已在变量maxDownloadMilliseconds
中指定了10秒(10000毫秒)的超时时间。
如果您确实想等待所有下载完成,请在不指定超时的情况下致电Task.WaitAll
。
使用
Task.WaitAll(tasks.ToArray());//wait to download
在这两个地方。
要了解关于如何实现并行下载,而不是强调系统中的一些好的解释(只能并行下载的最大数量),请参阅How can I limit Parallel.ForEach?
答案如果你不是第一次添加的所有下载任务,只有* *事后**等待他们完成?这就是我的做法。你正在做的事情 - 在将一个新线程放入池中完成后立即等待 - 看起来像是同步编程 - 换句话说,你没有从多线程中获益。这不直接涉及*不等待*但是......我正在离开作为一个评论。 – Veverke
@Veverke我是Tasks的新手,所以我想如果我全部添加了它们,假设有10,000个文件需要下载,所有任务都会同时运行,并且系统处理太多了。 - 为此我决定分批运行这些任务。 – Rick
那么我错过了你有2次等待的事实,我只看到了第一次。然后,我现在问别的问题:为什么你需要循环内的那个?你有没有尝试过一次运行?尝试评论for循环中的if,看看会发生什么。你有例外吗? – Veverke