如何等待最短的时间?

时间:2018-11-07 00:16:40

标签: c# .net asynchronous

我有一个异步C#方法,在这里我获取HTTP资源,并且在无限循环中执行它。但是,我不想太快地使用资源。我当前的代码是:

Import-Csv

但是,我希望能够确保我发出HTTP请求的频率不会超过每10秒一次。因此,我想在循环开始时启动一个10秒计时器,最后说“等待10秒计时器完成”。在C#.NET中有没有办法做到这一点?

5 个答案:

答案 0 :(得分:13)

最简单的方法:

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在立即完成的情况下所需的负担。

答案 1 :(得分:5)

在开始循环时创建一个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());

    int milliseconds = 10000 - sw.ElapsedMilliSeconds;
    if (milliseconds > 0)
    {
        await Task.Delay(milliseconds);
    }
}

答案 2 :(得分:3)

您可以为此使用简单的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);
}

答案 3 :(得分:1)

不确定这是否正是您要查找的内容,但是Task.Delay可以将循环暂停给定的毫秒数。

while (true)
{
 ... 
 await Task.Delay(10 * 1000);
}

答案 4 :(得分:1)

您可以结合使用CancellationTokenSourceTaskCompletionSource来创建一个“延迟”任务,该任务在请求开始时开始,并在请求完成时等待:

private static Task GetDelayTask(TimeSpan delay, object state = null)
{
    var taskSource = new TaskCompletionSource<object>();
    var cts = new CancellationTokenSource(delay);
    cts.Token.Register(() =>
    {
        taskSource.SetResult(state);
        cts.Dispose();
    });
    return taskSource.Task;
}

用法:

HttpClient http = new HttpClient();
while (true)
{
    var delayTask = GetDelayTask(TimeSpan.FromSeconds(10));
    // Long-poll the API
    var response = await http.GetAsync(buildUri());

    Console.WriteLine("Resp: " + response.ToString());
    Console.WriteLine("CONTENT:");
    Console.WriteLine(await response.Content.ReadAsStringAsync());
    await delayTask;
}