Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/docker/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Winapi 使用timeSetEvent解析WaitForSingleObject&;当时间到时_Winapi_Waitforsingleobject - Fatal编程技术网

Winapi 使用timeSetEvent解析WaitForSingleObject&;当时间到时

Winapi 使用timeSetEvent解析WaitForSingleObject&;当时间到时,winapi,waitforsingleobject,Winapi,Waitforsingleobject,我正在使用Win32多媒体计时器在发送大量UDP数据包之间设置延迟,但我发现由此产生的延迟远远超过了应有的时间。即使在使用Windows Miltimedia计时器并提高计时器分辨率时,~40ms的延迟有时也接近1000ms。下面是我使用的代码的简化版本: if( timeGetDevCaps(&tc,sizeof(TIMECAPS)) == TIMERR_NOERROR) { timeRes = min( max(tc.wPeriodMin,1), tc.wPerio

我正在使用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 );
    }
if(timeGetDevCaps(&tc,sizeof(TIMECAPS))==TIMERR\u NOERROR)
{
timeRes=min(max(tc.wPeriodMin,1),tc.wPeriodMax);
timeBeginPeriod(timeRes);
printf(“计时器分辨率:%u\n”,计时器分辨率);
}
/* ... */
while(ptrHead)
{
NALU_t*ptrLink=ptrHead;
无符号长tsNALU=ptrLink->timestamp-tsFirst;
printf(“时间戳:%umsec\n”,ptrLink->Timestamp/90);
int-idxPort;
对于(idxPort=0;idxPortptrData,ptrLink->lenData,
0,saAddr,lenAddr);
}
如果(1)
{
无符号长毫秒=(tsNALU-tsPrev)/90;
valTime.QuadPart=10000;
valTime.QuadPart*=毫秒;
valTime.QuadPart*=-1;
if(SetWaitableTimer(hdlTimer和valTime,0,NULL,NULL,TIME_ONESHOT))
WaitForSingleObject(hdlTimer,无限);
}
tsPrev=tsNALU;
ptrHead=ptrLink->next;
免费(ptrLink);
}

我怀疑问题在于Windows7不再保证事件发出信号时计时器的分辨率,而不是回调,但我讨厌使用后者。有人知道为什么单线程测试用例中的高分辨率计时器如此不准确吗?

如果计时非常关键,最好在繁忙的循环中运行(如果愿意,可以使用Sleep(0)放弃每次迭代的时间片),使用QueryPerformanceCounter()API测量经过的时间。

来自后续实验,我最好的猜测是,Windows在CPU核之间移动线程(可能是出于负载平衡的原因——这是在四核i7上)会破坏定时功能。我使用
SetThreadAffinityMask()
将计时关键线程锁定到一个CPU(将非计时线程锁定到所有其他内核),这样就解决了问题。

计时器的分辨率永远无法保证。他们仍然依赖于流程/系统正在做的任何其他事情。当没有加载时,它们应该足够接近。我知道将“保证”和“窗口”放在同一句话中是对术语的滥用,但WinMM的准确性不应该如此糟糕:)我本来打算避免繁忙的循环,但函数的MSDN页面上有一条关于使用SetThreadAffinityMask()的注释,这使我走上了正确的道路。