限制异步任务
我想运行一堆异步任务,并限制在任何给定时间可以完成的任务数量。
假设您有1000个网址,并且您只希望一次打开50个请求; 但只要一个请求完成,您就会打开与列表中下一个URL的连接。这样,一次只打开50个连接,直到URL列表用完为止。
如果可能的话,我也想利用给定数量的线程。
我提出了一种扩展方法,ThrottleTasksAsync
可以实现我想要的功能。那里有更简单的解决方案吗?我认为这是一种常见的情况。
用法:
class Program{ static void Main(string[] args) { Enumerable.Range(1, 10).ThrottleTasksAsync(5, 2, async i => { Console.WriteLine(i); return i; }).Wait(); Console.WriteLine("Press a key to exit..."); Console.ReadKey(true); }}
这是代码:
static class IEnumerableExtensions{ public static async Task<Result_T[]> ThrottleTasksAsync<Enumerable_T, Result_T>(this IEnumerable<Enumerable_T> enumerable, int maxConcurrentTasks, int maxDegreeOfParallelism, Func<Enumerable_T, Task<Result_T>> taskToRun) { var blockingQueue = new BlockingCollection<Enumerable_T>(new ConcurrentBag<Enumerable_T>()); var semaphore = new SemaphoreSlim(maxConcurrentTasks); // Run the throttler on a separate thread. var t = Task.Run(() => { foreach (var item in enumerable) { // Wait for the semaphore semaphore.Wait(); blockingQueue.Add(item); } blockingQueue.CompleteAdding(); }); var taskList = new List<Task<Result_T>>(); Parallel.ForEach(IterateUntilTrue(() => blockingQueue.IsCompleted), new ParallelOptions { MaxDegreeOfParallelism = maxDegreeOfParallelism }, _ =>
但是,线程池快速耗尽,你不能做async
/ await
。
额外: 为了解决调用时BlockingCollection
抛出异常的问题,我正在使用带超时的重载。如果我没有使用超时,它会破坏使用的目的,因为不会阻止。有没有更好的办法?理想情况下,会有一种方法。Take()
CompleteAdding()
TryTake
TryTake
BlockingCollection
TryTake
TakeAsync
至尊宝的传说
相关分类