【发布时间】:2021-10-29 23:49:12
【问题描述】:
我有一个 Windows 窗体应用程序,单击按钮时,我想循环一个整数列表并以每秒只能发出 50 个并行请求的方式进行 http post 调用。这是因为目标 http 端点仅支持每秒 50 个请求。为了实现这一点,这是我的逻辑:
我已将 SemaphoreSlim 节流器声明为全局变量:
var throttler = new SemaphoreSlim(50);
在按钮单击事件中,我正在遍历项目列表并进行 http 调用:
List<Task> lstTasks = new List<Task>();
foreach (var item in lstItems)
{
lstTasks.Add(CallAsyncMtd(item));
}
进行http调用的方法是:
private async Task CallAsyncMtd(int item, IProgress<int> progress)
{
await throttler.WaitAsync(); // here I am doing an async wait for the semaphore so that not more than 5 threads can run at the same time
try
{
await Task.Delay(1000).ConfigureAwait(false); //simulate an api call, configure await is false so the remaining code will run on separate thread
}
catch (Exception e)
{
//do some exception handling
}
//saveResponseToMySQL(response) //save the http response to mysql database synchronously
progress.Report(1); //report progress
await Task.Delay(1000 * 1); //wait for 1 second
throttler.Release(); //release semaphore
}
发出请求后,我正在等待 1 秒(在单独的线程中)。有没有更好的方法可以让我每秒发出 50 个请求,而不必按照上述逻辑再等待一秒钟?
【问题讨论】:
-
你还等什么呢?
-
信号量允许50个线程同时运行。我正在等待,以便在一秒钟内发出不超过 50 个请求。例如 - 如果我删除了 1 秒的等待,那么在一秒钟内可能会出现这样的情况,即发出 50 个请求,并且说其中 1 个已完成并发出第 51 个请求。我想防止这种情况发生。
-
定义“每秒”。你的意思是'一旦你开始一个请求,你就不能开始第 51 个请求,直到 1000 毫秒过去'(即时间窗口是基于第一个请求,还是基于时钟的第二个窗口)? 具体是什么速率限制规则?只有一个进程启动这些请求吗?您发起的请求总数是多少?您是否考虑过将多个数字传递给单个 API 调用(而不是发起多个 API 调用)?
-
需求文档说我们每秒最多只能发出 50 个请求。所以在一秒钟内不能有超过 50 个请求。如果我们确实提出超过 50 个,那么我们必须为所有请求支付费用。所以我想避免这笔费用。
-
Interlocked.Increment在每个请求上。每 45 个请求将当前时间与之前的 45 个请求进行比较。如果需要,添加睡眠。我认为如果你在await之前这样做,那么它应该做你想做的事。
标签: c# winforms asynchronous async-await