我目前正在使用Async CTP,需要将此代码转换为可以使用Task.WhenAll()的代码。
到目前为止我所做的是使用UserState对象并将我的标识符(AID)放入其中,然后在已完成的事件中使用它。
然而,wc.DownloadFileTaskAsync方法没有UserState的重载。我该怎么办?
for (int i = 0; i < SortedRecommendations.Count; i++)
{
string tempfilepath = filepath + SortedRecommendations[i].Aid + ".jpg";
if (File.Exists(tempfilepath))
continue;
WebClient wc = new WebClient();
wc.DownloadFileCompleted += (s, e) =>
{
var q = SortedRecommendations.Where(x => x.Aid == (int)e.UserState);
if (q.Count() > 0)
q.First().Image = tempfilepath;
};
wc.DownloadFileAsync(new Uri(SortedRecommendations[i].Image.Replace("t.jpg", ".jpg")), tempfilepath, SortedRecommendations[i].Aid);
}
这基本上与我提出的一样,但是我在y.Aid = = SortedRecommendations [i]得到一个out out限制异常.Aid因为我现在显然是其他的东西然后是下载开始的时候。我看到的其他可能性只是使用像TaskEx.Run(()=&gt; {//同步下载数据}这样的东西;但我不喜欢这种方法。
for (int i = 0; i < SortedRecommendations.Count; i++)
{
string tempfilepath = filepath + SortedRecommendations[i].Aid + ".jpg";
if (File.Exists(tempfilepath))
continue;
WebClient wc = new WebClient();
wc.DownloadFileCompleted += (s, e) =>
{
var q = SortedRecommendations.Where(x => x.Aid == SortedRecommendations[i].Aid);
if (q.Count() > 0)
q.First().Image = tempfilepath;
};
tasks.Add(wc.DownloadFileTaskAsync(new Uri(SortedRecommendations[i].Image.Replace("t.jpg", ".jpg")), tempfilepath));
}
await TaskEx.WhenAll(tasks);
//Everything finished
答案 0 :(得分:0)
首先,我认为你不应该把你的逻辑基于ids(除非你真的需要)。您应该使用SortedRecommendations
集合中对象的引用。
现在,如果您一次只想下载一个文件,只需使用await
:
for (int i = 0; i < SortedRecommendations.Count; i++)
{
string tempfilepath = filepath + SortedRecommendations[i].Aid + ".jpg";
if (File.Exists(tempfilepath))
continue;
WebClient wc = new WebClient();
var recommendation = SortedRecommendations[i];
await wc.DownloadFileTaskAsync(new Uri(recommendation.Image.Replace("t.jpg", ".jpg")), tempfilepath);
recommendation.Image = tempfilepath;
}
但是,如果您想同时启动所有下载,例如DownloadFileAsync()
代码,则可以使用ContinueWith()
。而且你不需要用户状态,这就是闭包的用途:
for (int i = 0; i < SortedRecommendations.Count; i++)
{
string tempfilepath = filepath + SortedRecommendations[i].Aid + ".jpg";
if (File.Exists(tempfilepath))
continue;
WebClient wc = new WebClient();
var recommendation = SortedRecommendations[i];
var downloadTask = wc.DownloadFileTaskAsync(new Uri(recommendation.Image.Replace("t.jpg", ".jpg")), tempfilepath);
var continuation = downloadTask.ContinueWith(t => recommendation.Image = tempfilepath);
tasks.Add(continuation);
}
await Task.WhenAll(tasks);
最好的解决方案可能是一次下载有限数量的文件,而不是一个或全部。这样做会更复杂,一个解决方案是使用ActionBlock
设置的TPL数据流中的MaxDegreeOfParallelism
。