我知道,对于计时准确性,timeGetTime,timeBeginPeriod,Query
PerformanceCounter等功能都很棒,同时具有良好的分辨率和优点.准确性,但仅基于启动时间,没有与时钟时间的直接链接.
但是,我不想这样的时间事件.我希望能够生成一个确切的时间戳(本地时间),以便我可以在日志文件中显示它,例如31-12-2010 12:38:35.345,对于每个条目. (我需要毫秒精度)
标准的Windows时间函数,如GetLocalTime,虽然它们提供毫秒值,但没有毫秒级的分辨率,具体取决于运行的操作系统.我正在使用XP,所以我不能指望比大约15ms的分辨率好多了.
我需要的是一种获得两全其美的方法,而不会产生大量开销来获得所需的输出.过大的方法/计算意味着记录仪在其运行期间会开始耗费太多时间.
最好/最简单的方法是什么?
首先,一些功能:
// ==========================================================================
#define NOMINMAX
#define _AFXDLL
#include "afxwin.h" // TRACE
#include "windows.h" // ULARGE_INTEGER
#include "mmSystem.h" // timeGetTime
#pragma comment(lib,"Winmm.lib") // timeGetTime
// ==========================================================================
// convert FILETIME to ULONGLONG
// (casting won't work on 64-bit platforms,due to alignment of FILETIME members)
inline void ToULL(const FILETIME& ft,ULONGLONG& uft)
{
ULARGE_INTEGER uli;
uli.LowPart = ft.dwLowDateTime ;
uli.HighPart= ft.dwHighDateTime;
uft= uli.QuadPart;
}
// --------------------------------------------------------------------------
// convert ULONGLONG to FILETIME
// (casting won't work on 64-bit platforms,due to alignment of FILETIME members)
inline void ToFILETIME(const ULONGLONG& uft,FILETIME& ft)
{
ULARGE_INTEGER uli;
uli.QuadPart= uft;
ft.dwLowDateTime = uli.LowPart ;
ft.dwHighDateTime= uli.HighPart;
}
// --------------------------------------------------------------------------
// ULONGLONG version for GetSystemTimeAsFileTime
inline void GetSystemTimeAsULL(ULONGLONG& uft)
{
FILETIME ft;
::GetSystemTimeAsFileTime(&ft);
ToULL(ft,uft);
}
// --------------------------------------------------------------------------
// convert ULONGLONG to time-components
bool ULLToSystemTime(const ULONGLONG nTime,// [i]
WORD& nYear,// [o] 1601 - 30827
WORD& nMonth,// [o] 1 - 12
WORD& nDay,// [o] 1 - 31
WORD& nHour,// [o] 0 - 23
WORD& nMinute,// [o] 0 - 59
WORD& nSecond,// [o] 0 - 59
WORD& nMilliseconds ) // [o] 0 - 999
{
SYstemTIME sysTime;
FILETIME ft ;
ToFILETIME(nTime,ft);
// the wDayOfWeek member of the SYstemTIME structure is ignored
if (0 == ::FileTimetoSystemTime(&ft,&sysTime))
return false;
nYear = sysTime.wYear ;
nMonth = sysTime.wMonth ;
nDay = sysTime.wDay ;
nHour = sysTime.wHour ;
nMinute = sysTime.wMinute ;
nSecond = sysTime.wSecond ;
nMilliseconds= sysTime.wMilliseconds;
return true;
}
// --------------------------------------------------------------------------
void TraceTime(const ULONGLONG nTime) // [i]
{
WORD nYear,nMonth,nDay,nHour,nMinute,nSecond,nMilliseconds;
ULLToSystemTime(nTime,nYear,nMilliseconds);
TRACE("Time: %02u-%02u-%04u %02u:%02u:%02u.%03u\n",nMilliseconds);
}
现在,如何使用:
ULONGLONG u0,u1;
::GetSystemTimeAsULL(u0);
// wait for tick (each 14.4mS)
do
{
::GetSystemTimeAsULL(u1);
}
while (u0==u1);
DWORD d1= ::timeGetTime();
// d1 and u1 are Now synchronized
// ... do some work
// get current time:
ULONGLONG u2= u1+(::timeGetTime() - d1)*10000; // mSec --> HectoNanoSec
TraceTime(u2);
请注意,您应该在2-3分钟内重新同步d1和u1一次,以保持准确性.实际上,您可以测量时钟之间的漂移,以找到最佳的重新同步间隔.