Мне нужно вызывать API тысячи раз как можно быстрее.API имеет ограничение в 10 вызовов в секунду.Чтобы в полной мере воспользоваться преимуществами 10 вызовов в секунду, не переходя, я вызываю API асинхронно и регулирую вызовы семафором и таймером.Мой код входит в семафор, вызывает API, а затем проверяет, что прошла хотя бы одна секунда, прежде чем он выпустит семафор.
Вызов API на самом деле довольно быстрый и возвращает примерно секунду или меньше, поэтому мойкод должен перейти прямо к логике проверки времени / выпуска семафора.Однако в действительности после 10 вызовов семафор заполняется и вообще не освобождается, пока не будут созданы остальные асинхронные задачи для вызова API.После этого все работает как положено, поэтому я не испытываю никаких реальных проблем.Поведение просто кажется странным, и я хотел бы понять это.
public static class MyClass
{
SemaphoreSlim semaphore = new SemaphoreSlim(10);
public static async Task CreateCallApiTasks(IList<object> requests)
{
var callApiTasks = requests.Select(x => CallApi(x));
await Task.WhenAll(callApiTasks);
}
private static async Task CallApi(object requestBody)
{
using (var request = new HttpRequestMessage(HttpMethod.Post, <apiUri>))
{
request.Content = new StringContent(requestBody, System.Text.Encoding.UTF8, "application/json");
HttpResponseMessage response = null;
using (var httpClient = new HttpClient())
{
var throttle = new Stopwatch();
ExceptionDispatchInfo capturedException = null;
await semaphore.WaitAsync();
try
{
throttle.Start();
response = await httpClient.SendAsync(request);
while (throttle.ElapsedMilliseconds < 1000)
{
await Task.Delay(1);
}
semaphore.Release();
throttle.Stop();
}
catch (Exception ex)
{
capturedException = ExceptionDispatchInfo.Capture(ex);
}
if (capturedException != null)
{
while (throttle.ElapsedMilliseconds < 1000)
{
await Task.Delay(1);
}
semaphore.Release();
throttle.Stop();
capturedException.Throw();
}
}
}
}
}