我有一个代码在asp.net web api中运行,从其他站点下载图像文件。
这是我用来下载图片的代码。
foreach (string file in images)
{
using (WebClient client = new WebClient())
{
await client.DownloadFileTaskAsync(file, path + Path.GetFileName(file));
}
}
我真正需要做的是一次启动10次下载。 (例如,使用Task.Run ......或任何其他方式),然后在最初启动的10逐个完成时逐个启动其余部分。
对于EX。
启动10个任务
等到10个任务中的一个完成
当1完成时,启动另一个任务
当另一个1完成时,启动另一个任务等......
直到下载列表中的所有图像为止。
因此,当代码运行时,我最多只能有10个并发下载(如果没有更多图像需要下载,则会少于10个。)
我正在使用.net 4.5.2
你们能指出我正确的方向来实现这个目标吗?
答案 0 :(得分:2)
您可以使用SemaphoreSlim
来限制异步工作:
private readonly SemaphoreSlim _mutex = new SemaphoreSlim(10);
...
var downloads = images.Select(file => DownloadAsync(file));
await Task.WhenAll(downloads);
...
private async Task DownloadAsync(string file)
{
await _mutex.WaitAsync();
try
{
using (WebClient client = new WebClient())
{
await client.DownloadFileTaskAsync(file, path + Path.GetFileName(file));
}
}
finally
{
_mutex.Release();
}
}
注意:
System.Net.ServicePointManager.DefaultConnectionLimit
。Task.Run
。有关详细信息,请参阅我的recent MSDN article on async
ASP.NET。答案 1 :(得分:0)
我在这里大声思考,不确定这是否有效,其他人希望能有所改进:
private void startFirst10Tasks()
{
List<Task> tasks = new List<Task>();
//tasks.Add first 10 tasks
taskHandler(tasks);
}
private void taskHandler(List<Task> tasks)
{
Task.Factory.ContinueWhenAny(tasks, winner =>
{
getNewTasks(tasks.Except(new List<Task>{winner}));
});
}
private void getNewTasks(List<Task> tasks)
{
tasks.Add(
Task.Factory.StartNew(() =>
{
//Next DownloadFileTask
})
);
taskHandler(tasks);
}