如何解决在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 举报,一经查实,本站将立刻删除。