使用timeSetEvent和&分辨率解决WaitForSingleObject SetWaitableTimer

时间:2012-08-30 15:01:57

标签: winapi waitforsingleobject

我正在使用Win32多媒体计时器在发送大量UDP数据包之间设置延迟,但我发现所产生的延迟远远超过应有的延迟。即使使用Windows Miltimedia定时器并提高定时器分辨率,~40ms的延迟有时会接近1000ms。下面是我使用的代码的简化版本:

if( timeGetDevCaps(&tc,sizeof(TIMECAPS)) == TIMERR_NOERROR) 
    {
    timeRes = min( max(tc.wPeriodMin,1), tc.wPeriodMax);
    timeBeginPeriod(timeRes);
    printf("Timer Res: %u\n", timeRes);
    }
/* ... */
while( ptrHead )
    {
    NALU_t *ptrLink = ptrHead;
    unsigned long tsNALU = ptrLink->timestamp - tsFirst;
    printf("Timestamp: %umsec\n", ptrLink->timestamp / 90 );
    int idxPort;
    for(idxPort=0;idxPort<12;idxPort++)
        {
        ip4Addr.sin_port = htons( 60000 + idxPort );
        struct sockaddr *saAddr = (struct sockaddr*)&ip4Addr;
        sendto(fdSocket,(char*)ptrLink->ptrData,ptrLink->lenData,
           0,saAddr,lenAddr);
        }
    if( 1 )
        {
        unsigned long millis = (tsNALU - tsPrev) / 90;
        valTime.QuadPart  = 10000;
        valTime.QuadPart *= millis;
        valTime.QuadPart *= -1;
        if(SetWaitableTimer(hdlTimer,&valTime,0,NULL,NULL,TIME_ONESHOT))
            WaitForSingleObject(hdlTimer,INFINITE);
        }
    tsPrev = tsNALU;
    ptrHead = ptrLink->next;
    free( ptrLink );
    }

怀疑问题在于,当事件发出信号而不是回叫时,Windows7不再保证定时器的解析,但我厌恶使用后者。任何人都知道为什么在单线程测试用例中的高分辨率计时器被认为是非常不准确的?

2 个答案:

答案 0 :(得分:1)

如果时序至关重要,最好在繁忙的循环中运行(如果需要,可以使用Sleep(0)每次迭代放弃一个时间片),使用QueryPerformanceCounter()API来测量经过的时间。

答案 1 :(得分:1)

从后续实验中,我最好的猜测是Windows在CPU内核之间移动线程(可能出于负载平衡的原因 - 这是在四核i7上)会对时序功能造成破坏。我使用SetThreadAffinityMask()将我的时序关键线程锁定到一个CPU(以及我的非时序线程到所有其他内核),并且已经解决了问题。