Noda 时间和经常性操作 (c#)

Noda Time and recurrent operations (c#)

我正在尝试编写一个 'pinging' 代码,该代码将 post 每隔一分钟提供一次休息服务。

我最简单的 'old' 方法如下:

while (true)
{
    if (cancellationToken.IsCancellationRequested)
    {
        return;
    }

    await Task.Delay(TimeSpan.FromMinutes(1), cancellationToken);

    try
    {
        await PingImpl(clientId, baseUri, cancellationToken);
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "ping {BaseUri} {Endpoint} failed", baseUri, Endpoint);
    }
}

现在,为了对服务器的循环调用进行单元测试,我通常会在生产中注入延迟持续时间为一毫秒,在生产中注入一分钟(我知道它会轮询 'slower' 而不是一次分钟,因为执行一个请求需要时间,可以接受)

现在,有了#codatime,我不想搞乱注入参数,并希望在 IClock 上有一些扩展,比如

   await _clock.Delay(...);

然后,单元测试代码将推进假时钟并触发操作。

你知道实现这种行为的一些优雅方法吗?

IClock 没有任何延迟的概念 - 它 回答了“现在几点”的问题。

你想要的是不同的抽象。在我作为 Google 云客户端库的一部分维护的 GAX 项目中,我们有 this abstraction:

public interface IScheduler
{
    Task Delay(TimeSpan delay, CancellationToken cancellationToken);
}

就像 IClock 一样,还有一个使用 Task.Delay 的单例实现 - 和一个推进时钟的 test implementation。我会说随着时间的推移,测试实施给我们带来了很多问题,因为模拟是一件非常复杂的事情。您不能只提前时钟然后 return 完成任务 - 因为您希望其他异步调用在开始和完成延迟之间的“模拟时间”内发生。

当然,您可能有更简单的要求 - 如果您没有任何其他事情要做,您可能能够提前时钟。但请注意它的局限性,因为其他异步操作不会同时发生。

这里的基本想法非常有用 - 但实施起来确实很麻烦。