微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在System.Threading.Timer过去之后,DateTime.UtcNow是否可能报告错误的时间?

如何解决在System.Threading.Timer过去之后,DateTime.UtcNow是否可能报告错误的时间?

我有一段代码将当前时间(DateTime.UtcNow)记录为“截止期限”,设置了System.Threading.Timer,并在计时器经过时检查是否已达到截止日期。它通过将当前时间(DateTime.UtcNow)与记录的截止日期进行比较来进行此检查。

这是一个简化的代码示例,阐明了原理:

class DeadlineChecker
{
  private DateTime deadline;

  public DeadlineChecker()
  {
    int waitingTimeInMilliseconds = 1200;

    TimeSpan waitingTime = TimeSpan.FromMilliseconds(waitingTimeInMilliseconds);
    this.deadline = DateTime.UtcNow + waitingTime;

    System.Threading.Timer timer = new System.Threading.Timer(TimerElapsed);
    timer.Change(waitingTimeInMilliseconds,Timeout.Infinite);
  }

  private void TimerElapsed(object state)
  {
    if (this.HasDeadlineBeenReached())
    {
      [...]  // Do something
    }

    [...] // Cleanup (dispose timer etc.)
  }

  private bool HasDeadlineBeenReached
  {
    get
    {
      // This is only called from TimerElapsed(),so
      // this should always return true,right?
      return (this.deadline <= DateTime.UtcNow);
    }
  }
}

我现在遇到HasDeadlineBeenReached意外返回false的情况。看来我对HasDeadlineBeenReached在上述示例代码中始终返回true的假设是错误的。

有人可以解释为什么吗?在重构之前,我想了解这个问题。

即使考虑到已记录的事实,DateTime.UtcNow的分辨率为15毫秒,我也不希望在时间X和Y拍摄的DateTime.UtcNow的两个快照报告的时间跨度小于实际发生了什么(Y-X)。即使两个快照都关闭了15ms,它们之间的时间间隔仍应等于由于计时器而经过的时间?

编辑:真正的代码试图做的是设置一个截止日期,在某些事件发生时检查该截止日期,并在达到该截止日期时“执行某些操作”。 “计时器已逝”事件只是触发截止日期检查的众多事件之一,并且可以保证在没有其他事件的情况下发生“执行某事”。 “做某事”是否按时完成还是比截止日期晚几毫秒甚至一秒都没关系-只需保证即可做到。

编辑2:在接受答案后,我对代码示例进行了一些小的更改-我知道,这是不好的风格,但是也许这使后代的问题更容易理解。

解决方法

您写道:

// This should always return true,right?

否,只有在截止日期过去时才返回true。我很高兴您为将来设置了一个1200ms的截止日期,然后告诉计时器在1200ms之后触发,并期望该截止日期在计时器启动的那一刻过去,但实际上计时器的计时和精度Clock这样的话,您很可能会合理地观察到代码没有按预期的毫秒数触发,并且时钟没有返回预期的精确毫秒数,因此,您的截止日期仍在代码运行的将来。

我建议您调整计时策略;将您的计时器设置为您希望“准确”的间隔的一半,使用相同的逻辑检查您的截止日期为过去,并容忍不精确的行为(不要向用户保证他们可以安排他们的通知时间达到1毫秒的精度)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。