c# - SemaphoreSlim 不会限制任务
问题描述
我创建了以下方法 TestThrottled 来尝试限制我的任务,但是当我调用 WhenAll 并且此方法都具有相同的经过时间时,它根本没有限制。我做错什么了吗?
private static async Task<T[]> TestThrottled<T>(List<Task<T>> tasks, int maxDegreeOfParallelism)
{
var semaphore = new SemaphoreSlim(maxDegreeOfParallelism);
var tasksParallelized = new List<Task<T>>();
foreach (var task in tasks)
{
var taskParallelized = Task.Run(async () =>
{
try
{
await semaphore.WaitAsync();
return await task;
}
finally
{
semaphore.Release();
}
});
tasksParallelized.Add(taskParallelized);
}
return await Task.WhenAll(tasksParallelized);
}
private static async Task<int> TestAsync()
{
await Task.Delay(1000);
return 1;
}
static async Task Main(string[] args)
{
var sw = Stopwatch.StartNew();
var tasks = new List<Task<int>>();
var ints = new List<int>();
for (int i = 0; i < 30; i++)
{
tasks.Add(TestAsync());
}
ints.AddRange(await TestThrottled(tasks, 1));
Console.WriteLine($"{sw.ElapsedMilliseconds}, count: {ints.Count}");
Console.ReadLine();
}
解决方案
另一种方法是使用TPL DataFlow,它已经拥有您需要的一切,并且可以在需要时满足更复杂的流水线操作,并且具有更多的可配置性。它还可以节省您卸载到另一个任务的时间,就像您的示例解决方案一样
private static async Task<IList<T>> TestThrottled<T>(IEnumerable<Func<Task<T>>> tasks, int maxDegreeOfParallelism)
{
var options = new ExecutionDataflowBlockOptions() { EnsureOrdered = false, MaxDegreeOfParallelism = maxDegreeOfParallelism };
var transform = new TransformBlock<Func<Task<T>>, T>(func => func.Invoke(), options);
var outputBufferBlock = new BufferBlock<T>();
transform.LinkTo(outputBufferBlock, new DataflowLinkOptions(){PropagateCompletion = true});
foreach (var task in tasks)
transform.Post(task);
transform.Complete();
await outputBufferBlock. Completion;
outputBufferBlock.TryReceiveAll(out var result);
return result;
}
推荐阅读
- python - 在数据帧上申请循环?
- c - 如何从其他函数访问结构数组并赋值
- javascript - 使用 getElementById() 发出警报
- python - 无法在 python 3 中触发 elif/else 条件
- c - 错误:“MAP_SYNC”未声明和错误:“MAP_SHARED_VALIDATE”
- java - Java中连续四次游戏中的错误
- hyperledger-fabric - Hyperledger Fabric 2.0 无法解析来自 evaluateTransaction 的结果
- google-apps-script - 根据来自另一个特定单元格范围的值从特定范围删除谷歌电子表格中的行
- lua - Lua 关系运算符不工作,Rainmeter 中的脚本
- java - 编译器会优化不改变的参数吗?