我有一个异步C#方法,在这里我获得了一个HTTP资源,并且我在一个无限循环中这样做。但是,我不想太快地访问资源。我目前的代码是:
HttpClient http = new HttpClient();
while (true) {
// Long-poll the API
var response = await http.GetAsync(buildUri());
Console.WriteLine("Resp: " + response.ToString());
Console.WriteLine("CONTENT:");
Console.WriteLine(await response.Content.ReadAsStringAsync());
}但是,我希望能够确保每10秒发出HTTP请求的次数不会超过一次。因此,我想在循环开始时启动一个10秒计时器,最后说“等待10秒定时器的完成”。在C#.NET中有办法做到这一点吗?
发布于 2018-11-07 00:21:28
最简单的:
while (true) {
var rateLimit = Task.Delay(TimeSpan.FromSeconds(10));
// ...await your http/whatever
await rateLimit;
}如果http工作占用了10秒时间,await rateLimit将立即完成。
但是,您可以选择比较http工作之前和之后的时间,看看您是否需要等待;更像是:
while (true) {
var timeBefore = ...
// ...await your http/whatever
var timeAfter = ...
// ... calculate time left
if (timeLeft > TimeSpan.Zero) await Task.Delay(timeLeft);
}这避免了Task.Delay将立即完成的场景中所需的管道。
发布于 2018-11-07 00:23:21
在启动循环时创建一个StopWatch (并启动它)。
然后,当GetAsync方法返回时,读取ElapsedMilliseconds。从10000减去这个值。现在做:
await Task.Delay(yourValue);现在只需要分钟。一圈10秒。
守则:
while (true) {
// Long-poll the API
Stopwatch sw = Stopwatch.StartNew();
var response = await http.GetAsync(buildUri());
Console.WriteLine("Resp: " + response.ToString());
Console.WriteLine("CONTENT:");
Console.WriteLine(await response.Content.ReadAsStringAsync());
long milliseconds = 10000 - sw.ElapsedMilliseconds;
if (milliseconds > 0)
{
await Task.Delay((int)milliseconds);
}
}发布于 2018-11-07 00:24:51
为此您可以使用一个简单的StopWatch,并使用Task.Delay等待所需的时间(如果有的话)。
const int minimumTime = 10_000;
var sw = StopWatch.StartNew();
while (true)
{
// Long-poll the API
var response = await http.GetAsync(buildUri());
...
int difference = minimumTime - sw.EllapsedMiliseconds;
if (difference > 0)
{
await Task.Delay(difference);
}
sw.Restart();
}但是,这只适用于每次调用之间需要10秒的情况。如果API需要9秒才能完成,那么每秒就会接到2个调用。
如果您希望始终等待10秒,不管API完成花费了多少时间,只需使用:
const int waitTime = 10_000;
while (true)
{
// Long-poll the API
var response = await http.GetAsync(buildUri());
...
await Task.Delay(waitTime);
}https://stackoverflow.com/questions/53181980
复制相似问题