我正在使用DateTime.UtcNow来测量我的软件中的时间,并且需要能够判断“动作a”是否在“动作b”后不到10秒发生
但是,如果系统时间发生变化怎么办?那么我怎么做才能检测系统时间是否改变了?
我不想使用秒表,因为我们需要在具有多个CPU的服务器上运行,请参阅http://kristofverbiest.blogspot.com/2008/10/beware-of-stopwatch.html
我还需要处理被暂停和重新启动的虚拟机,因此“滴答计数”不太可能对我有用。
答案 0 :(得分:9)
您可以使用SystemEvents.TimeChanged
事件来检测更改的时间。但是,只有在运行了一个messagepump时才会激活 - 这对于Windows客户端应用程序来说很好,但对于大多数服务器应用程序(如服务,Web应用程序等)来说并不是那么多。
否则你可以使用Environment.TickCount
- 它没有很好的分辨率,但是如果你的“10”秒可以“接近10秒”你可能没问题。就虚拟机的限制而言,请注意当机器启动时间过长时,TickCount会翻转,因此您必须处理该问题,可能需要进行DateTime.UtcNow
完整性检查。
我会使用两者的组合 - 但请注意除了检查一些已知准确的外部时间服务器(这将会产生性能影响)之外没有绝对准确的方法,无论如何都会在VM情况下工作......确保在花费更多时间之前确定什么是“足够可靠”。
答案 1 :(得分:4)
我仍然建议使用StopWatch
。如果Beware of QueryPerformanceCounter中描述的问题仍然存在,那么您只会说几毫秒的差异。如果你担心负面时间(我从未见过的东西,并且我经常使用StopWatch
计算一些非常小的间隔),那么将-1毫秒和-1,000毫秒之间的任何东西都视为零。
如果有人更改了计算机上的日期/时间,那么使用DateTime.Now
或DateTime.UtcNow
进行任何类型的计时都会给您带来麻烦。您必须使用完全在计算机内部且无法更改的内容。 StopWatch
是我发现的最可靠的。
答案 2 :(得分:1)
您可以使用SystemEvents类的TimeChanged事件来检测运行时系统时钟的更改:
http://msdn.microsoft.com/en-us/library/microsoft.win32.systemevents.timechanged.aspx
这依赖于你的应用程序有一个消息循环(我假设因为需要处理WM_TIMECHANGED消息)所以如果它是无头应用程序,你将需要一个隐藏的形式,例如Windows服务。
至于在您的应用程序暂停时由于处于暂停的虚拟机而检测到系统时钟的更改 - 所有投注都是真正可靠的解决方案。您可以定期记录上次执行检查的时间,并确保时间没有倒退。无论如何,暂停和恢复VM可能需要超过十秒的时间。
答案 3 :(得分:0)
我会将系统时差与2个时间间隔之间的单色时钟进行比较。如果差异大于某些容差,则有人改变了您机器上的日期和时间