using System; using System.Threading; using System.Linq; using System.Diagnostics; using System.Collections.Generic; using System.Threading.Tasks; public class Test { private const int threads = 5; private const int items = 100; private const int downloadOne = 100; private const int waitLast = 1000; public static void Main() { Download9000Images(Enumerable.Range(1, items).Select(a=>"https://e...content-available-to-author-only...e.com/"+a.ToString()), "test").Wait(); } private static async Task Download9000Images( IEnumerable images, string outputdir ) { var sem = new SemaphoreSlim(threads); //var httpclient = new HttpClient(); var sw = new Stopwatch(); sw.Start(); Func download = async link => { try { await Task.Delay(downloadOne);//на ideone запрещён доступ к файлам/сети -> просто ждём Console.WriteLine("Link {0} downloaded", link); } catch { Console.WriteLine( "Failed to load {0}", link ); //тут хорошо бы удалять зафейленный файл } finally { sem.Release(); } }; foreach ( var image in images ) { await sem.WaitAsync(); var imgClosure = image;//до пятого шарпа захват иначе работает. пишешь на свежем - можешь забить download( imgClosure );//специально без await, чтобы продолжить цикл не дожидаясь завершения } sw.Stop(); await Task.Delay( waitLast );//тут по-хорошему надо дождаться всех тасков нормально, но мне лень писать Console.WriteLine("Прошло {0}", sw.Elapsed); Console.WriteLine("Тут должно всё было скачаться"); } }