具有可变周期的WaitableTimer

WaitableTimer with variable period

本文关键字:WaitableTimer 周期      更新时间:2023-10-16

我需要设置一个周期性执行的可等待计时器。

问题如下,周期每X个周期(比如说5个周期)变化一次,这取决于系统在最后5个周期执行任务所花费的时间。

我尝试使用一个自动重置等待计时器,它在每次迭代后都会被设置(5次中有4次间隔相同)。然而,时间与我设置的内容无关。相关代码如下所示。(一切都从调用HandleSensor开始)

    float AnalysisClient::GetNewInterval()
    {
        ...
            return newInterval;
    }
    VOID CALLBACK AnalysisClient::TimerFinished(LPVOID lpArg,
        DWORD dwTimerLowValue,
        DWORD dwTimerHighValue)
    {
        LARGE_INTEGER t;
        AnalysisClient* This = (AnalysisClient*)lpArg;
        This->readsensor();
        t.QuadPart = GetNewInterval() * 10000i64;
        SetWaitableTimer(_sensorTimer, &t, 0, TimerFinished, This, TRUE);
    }

    void AnalysisClient::WaitForsensor()
    {
        LARGE_INTEGER t;
        t.QuadPart = 0;
        SetWaitableTimer(_sensorTimer, &t, 0, TimerFinished, this, TRUE);
        SleepEx(
            INFINITE,           // Wait forever.
            TRUE);
    }

    void AnalysisClient::readsensor()
    {
        EnterCriticalSection(&_sensorCS);
        {
            while (_numsensorSampled >= _capacity) //no more sensors than the capacity size
            {
                UtilsLog("Queue full, not doing more sensor readings", UtilsDebug);
                SleepConditionVariableCS(&_sensorQueueFullCV, &_sensorCS, INFINITE);
            }
            UtilsLog("Read sensor", UtilsDebug);
            void* sensorreading = _fnSamplesensor();
            _numsensorSampled++;
            _localsensorQueue.push(sensorreading);
            _sensorHandler->Sendreading(sensorreading);
        }
        WakeConditionVariable(&_sensorQueueEmptyCV);
        LeaveCriticalSection(&_sensorCS);
    }
    void* AnalysisClient::Handlesensor()
    {
        //Spawn async thread if not already started
        if (!_asyncsensorHandlerStarted)
        {
            _asyncsensorHandlerStarted = true;
            CreateUtilsThread(Asyncreadsensor, this);
        }

        //Free memory from previous invocations
        ...
            void* returnVal = NULL;

        EnterCriticalSection(&_sensorCS);
        {
            while (_localsensorQueue.empty())
                SleepConditionVariableCS(&_sensorQueueEmptyCV, &_sensorCS, INFINITE);
            _lastreading = _localsensorQueue.front();
            _localsensorQueue.pop();
            returnVal = _lastreading;
            _numsensorProcessed++;
        }
        LeaveCriticalSection(&_sensorCS);
        return returnVal;
    }

    DWORD WINAPI AnalysisClient::Asyncreadsensor(void* Param)
    {
        //Create sensor Timer
        _sensorTimer = CreateWaitableTimer(NULL, FALSE, NULL);
        if (!_sensorTimer)
        {
            UtilsLog("Unable to create sensor waitable timer", UtilsError);
            return 1;
        }
        AnalysisClient* This = (AnalysisClient*)Param;
        This->WaitForsensor();
        return 0;
    }

bool CreateKahawaiThread(LPTHREAD_START_ROUTINE function, void* instance)
{
   DWORD ThreadID;
   HANDLE thread = CreateThread(NULL,0,function, instance, 0, &ThreadID);
   if(thread==NULL)
       return false;
   return true;
}

执行日志显示了以下执行(右边的数值是消息写入日志时的时间(以毫秒为单位)。zi调整了对GetNewInterval的调用,使其始终返回1600000i64,这样我就可以将其作为问题源丢弃。不过,计时器调用之间的时间与此无关。可以看到的容量设置为5。

        30621, Read sensor
        30623, Read sensor
        30624, Read sensor
        30625, Read sensor
        30626, Read sensor
        30627, Queue full, not doing more sensor readings
        30980, Read sensor
        30981, Queue full, not doing more sensor readings
        30997, Read sensor
        30998, Queue full, not doing more sensor readings
        31007, Read sensor
        31008, Queue full, not doing more sensor readings
        31019, Read sensor
        31020, Queue full, not doing more sensor readings
        31032, Read sensor
        31033, Queue full, not doing more sensor readings
        31040, Read sensor
        31041, Queue full, not doing more sensor readings
        31054, Read sensor
        31055, Queue full, not doing more sensor readings
        31066, Read sensor
        31068, Queue full, not doing more sensor readings
        31080, Read sensor
        31081, Queue full, not doing more sensor readings
        31087, Read sensor
        31088, Queue full, not doing more sensor readings
        31094, Read sensor
        31096, Queue full, not doing more sensor readings
        31111, Read sensor
        31112, Queue full, not doing more sensor readings
        31121, Read sensor
        31123, Queue full, not doing more sensor readings
        31180, Read sensor
        31181, Queue full, not doing more sensor readings
        31194, Read sensor
        31197, Queue full, not doing more sensor readings
        31294, Read sensor
        31295, Queue full, not doing more sensor readings
        31307, Read sensor
        31308, Queue full, not doing more sensor readings
        31316, Read sensor
        31318, Queue full, not doing more sensor readings
        31332, Read sensor
        31333, Queue full, not doing more sensor readings
        31336, Read sensor
        31337, Queue full, not doing more sensor readings
        31343, Read sensor
        31344, Queue full, not doing more sensor readings
        31359, Read sensor
        31360, Queue full, not doing more sensor readings
        31369, Read sensor
        31371, Queue full, not doing more sensor readings
        31384, Read sensor
        31385, Queue full, not doing more sensor readings
        31391, Read sensor
        31392, Queue full, not doing more sensor readings
        31398, Read sensor
        31399, Queue full, not doing more sensor readings 

错误是什么?有没有更好的方法来实现这一点?

感谢

您有

        while (_numsensorSampled >= _capacity) //no more sensors than the capacity size

        _localsensorQueue.push(sensorreading);
        _numsensorSampled++;

        _localsensorQueue.pop();
        returnVal = _lastreading;
        _numsensorProcessed++;

但没有

        --_numsensorSampled;

所以

        while (_numsensorSampled >= _capacity) //no more sensors than the capacity size

当你达到这个数字时,就会一直是真的。将其更改为

        while (_numsensorSampled - numsensorProcessed >= _capacity) //no more sensors than the capacity size

也应该让它发挥作用。还有

    WakeConditionVariable(&_sensorQueueEmptyCV);
    LeaveCriticalSection(&_sensorCS);

看起来不对,也许应该是

    LeaveCriticalSection(&_sensorCS);
    WakeConditionVariable(&_sensorQueueEmptyCV);

否则,由于关键部分仍然处于活动状态,被唤醒的进程可能会立即再次进入睡眠状态。