1

Win32 マルチメディア タイマーを使用して、多数の UDP パケットのディスパッチ間に遅延を設定していますが、結果として遅延が本来よりも大幅に長くなることがわかりました。Windows Miltimedia タイマーを使用してタイマーの解像度を上げた場合でも、最大 40 ミリ秒の遅延が 1000 ミリ秒近くになることがあります。以下は、私が使用したコードの簡略版です。

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がタイマーの解決を保証しなくなったことだと思いますが、後者を使用するのは嫌です。シングルスレッドのテストケースで高解像度と思われるタイマーでさえ、なぜそれほど不正確なのか知っている人はいますか?

4

2 に答える 2

1

タイミングが重要な場合は、QueryPerformanceCounter()APIを使用して経過時間を測定し、ビジーループで実行するのが最適です(必要に応じて、Sleep(0)を使用して反復ごとにタイムスライスを放棄できます)。

于 2012-08-31T05:49:29.180 に答える
1

その後の実験から、Windows が CPU コア間でスレッドを移動すると (おそらく負荷分散の理由で - これはクアッドコア i7 上にあります)、タイミング機能が破壊されると思われます。以前SetThreadAffinityMask()は、タイミングが重要なスレッドを 1 つの CPU にロックしていました (そして、タイミングが重要でないスレッドを他のすべてのコアにロックしていました)。これで問題は解決しました。

于 2012-08-31T16:45:09.173 に答える