Update 2022-12-22:
public static async Task<IEnumerable<T>> RunParallel<T>(int concurrency, IEnumerable<Func<Task<T>>> actions) { using (var semaphore = new SemaphoreSlim(concurrency)) { var tasks = new List<Task<T>>(); foreach (var action in actions) { await semaphore.WaitAsync(); var t = Task.Run(async () => { try { return await action(); } finally { semaphore.Release(); } }); tasks.Add(t); } return await Task.WhenAll(tasks); } } // example use: var tasks = new List<Func<Task<bool>>>(); foreach (var myTask in myTasks) { tasks.Add(() => myTask("A", "B")); } var results = await RunParallel(3, tasks);
Original:
using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; class Program { public static async Task RunParallel<T>(int concurrency, IEnumerable<T> args, Func<T, Task> action) { using (var semaphore = new SemaphoreSlim(concurrency)) { var tasks = new List<Task>(); foreach (var arg in args) { await semaphore.WaitAsync(); var t = Task.Run(async () => { try { await action(arg); } finally { semaphore.Release(); } }); tasks.Add(t); } await Task.WhenAll(tasks); } } static async Task Main(string[] args) { var arguments = Enumerable.Range(1, 15).Select(e => e.ToString()).ToList(); await RunParallel(3, arguments, async (a) => { Console.WriteLine("Start: " + a); await Task.Delay(2000); Console.WriteLine("End: " + a); }); Console.WriteLine("Finished!"); } }
402200cookie-checkC# Task RunParallel