因此,我刚刚被要求将我们正在调用的特定API的.Net异步代码的调用次数限制为5 /秒。
异步调用示例
var mylist = new List<Task<ApplicantDetails>>();
foreach (JToken result in results)
{
mylist.Add(getCandidateResumeAsync(result));
}
await Task.WhenAll(mylist);
以及对getCandidateResumeAsync
的API insode的实际调用
var candiateAttachmentsResponse = await Client.GetAsync(model["candidate"]["links"]["self"] + "/attachments");
我只需要每秒执行5次getCandidateResumeAsync
函数。
关于我该如何处理的任何想法?
答案 0 :(得分:3)
我将使用一个信号量来跟踪当前正在运行对该API的调用,然后在每次调用结束时释放一个。像这样:
public class Throttle
{
private readonly TimeSpan perPeriod = TimeSpan.FromSeconds(1);
private readonly SemaphoreSlim actionSemaphore = new SemaphoreSlim(5, 5);
public async Task Queue(Func<Task> action, CancellationToken cancel)
{
await actionSemaphore.WaitAsync(cancel);
try
{
await action();
}
finally
{
await Task.Delay(perPeriod, cancel).ContinueWith(_ => actionSemaphore.Release(1), cancel);
}
}
}
perPeriod将设置为1秒,而actionSemaphore将设置为5,这意味着它将允许一次运行5个请求。您会这样称呼它:
Throttle t = new Throttle();
t.Queue(SomeAction, CancellationToken.None);
然后您可以等待所有任务完成。
答案 1 :(得分:0)
在这种情况下,您可以限制并行任务,而不是限制每秒的任务。
static async Task Main(string[] args) {
const ushort maxConcurrentTasks = 5;
var resultBag = new ConcurrentBag<ApplicantDetails>();
var queue = new ConcurrentQueue<JToken>(items);
var tasks = Enumerable.Range(0, maxConcurrentTasks)
.Select(_ => GetResultAsync(queue, resultBag));
await Task.WhenAll(tasks);
var result = resultBag.ToArray();
}
private static async Task GetResultAsync(ConcurrentQueue<JToken> queue, ConcurrentBag<ApplicantDetails> resultBag) {
while (queue.TryDequeue(out var queueItem)) {
var result = await getCandidateResumeAsync(queueItem);
resultBag.Add(result);
}
}
我知道这并不是您要找的东西。但是也许您也可以接受这种方法。
答案 2 :(得分:0)
感谢所有的建议。
只需添加它,以防将来对其他人有帮助。
这是我想出的,它似乎运行正常。
int counter = 0;
foreach (JToken result in results)
{
counter++;
if ((counter % 5) == 0) Task.Delay(1000);
mylist.Add(getCandidateResumeAsync(result));
}