Qt计时器无法从另一个线程停止

Mat*_*att 11 c++ qt multithreading qthread qtimer

HY,

我正在编写我的第一个Qt程序,现在遇到麻烦:

QObject :: killTimer:无法从另一个线程停止计时器

QObject :: startTimer:无法从另一个线程启动计时器

我的程序将与CANOpen总线通信,因为我正在使用Canfestival Stack.Canfestival将使用回调方法.为了检测通信中的超时,我设置了一个定时器功能(以某种方式像看门狗).我的计时器包由"tmr"模块,"TimerForFWUpgrade"模块和"SingleTimer"模块组成."tmr"模块最初是C编程的,因此静态"TimerForFWUpgrade"方法将对其进行接口."tmr"模块将成为C程序固件更新包的一部分.

计时器将如下工作.在发送消息之前,我将调用TMR_Set方法.然后在我的空闲程序循环中使用TMR_IsElapsed我们检查定时器下溢.如果TMR_IsElapsed我会做错误处理.如您所见,将连续调用TMR_Set方法并一次又一次地重新启动QTimer.

如果我启动程序,就会出现上述错误.你能告诉我我的概念是否有效吗?为什么会出现这种错误?我是否必须在主线程中使用其他线程(QThread)?

谢谢

马特

运行和空闲循环:

void run
{
    // start communicate with callbacks where TMR_Set is set continously
    ...

    while(TMR_IsElapsed(TMR_NBR_CFU) != 1);

    // if TMR_IsElapsed check for errorhandling
    ....
}  
Run Code Online (Sandbox Code Playgroud)

模块tmr(C程序的接口):

extern "C"
{
void TMR_Set(UINT8 tmrnbr, UINT32 time)
{
    TimerForFWUpgrade::set(tmrnbr, time);
}

INT8 TMR_IsElapsed(UINT8 tmrnbr)
{
 return TimerForFWUpgrade::isElapsed(tmrnbr);
}
}
Run Code Online (Sandbox Code Playgroud)

模块TimerForFWUpgrade:

SingleTimer* TimerForFWUpgrade::singleTimer[NR_OF_TIMERS];

TimerForFWUpgrade::TimerForFWUpgrade(QObject* parent)
{

    for(unsigned char i = 0; i < NR_OF_TIMERS; i++)
    {
        singleTimer[i] = new SingleTimer(parent);
    }
}

//static
void TimerForFWUpgrade::set(unsigned char tmrnbr, unsigned int time)
{
    if(tmrnbr < NR_OF_TIMERS)
    {
        time *= TimerForFWUpgrade::timeBase;
        singleTimer[tmrnbr]->set(time);
    }

}


//static
char TimerForFWUpgrade::isElapsed(unsigned char tmrnbr)
{
    if(true == singleTimer[tmrnbr]->isElapsed())
    {
        return 1;
    }
    else
    {
        return 0;
    }
}
Run Code Online (Sandbox Code Playgroud)

模块SingleTimer:

SingleTimer::SingleTimer(QObject* parent) : QObject(parent),
                                            pTime(new QTimer(this)),
                                            myElapsed(true)
{
    connect(pTime, SIGNAL(timeout()), this, SLOT(slot_setElapsed()));
    pTime->setTimerType(Qt::PreciseTimer);
    pTime->setSingleShot(true);
}

void SingleTimer::set(unsigned int time)
{
    myElapsed = false;
    pTime->start(time);
}

bool SingleTimer::isElapsed()
{
    QCoreApplication::processEvents();
    return myElapsed;
}

void SingleTimer::slot_setElapsed()
{
    myElapsed = true;
}
Run Code Online (Sandbox Code Playgroud)

UmN*_*obe 7

您遇到此问题是因为静态数组中的计时器是在中创建的Thread X,但是已启动并停止Thread Y.这是不允许的,因为Qt依赖线程亲和性来超时计时器.

您可以在同一个线程中创建,启动停止,也可以使用信号和插槽来触发startstop操作定时器.信号和插槽解决方案有点问题因为您有nQTimer对象(提示:如何在位置启动计时器i?)

你可以做的反而是创建和初始化在位置计时器tmrnbr

TimerForFWUpgrade::set(unsigned char tmrnbr, unsigned int time)
{
     singleTimer[tmrnbr] = new SingleTimer(0);
     singleTimer[tmrnbr]->set(time);
}
Run Code Online (Sandbox Code Playgroud)

这是由同一个线程执行的.

此外,你不需要SingleTimer上课.您正在使用Qt5,您已经拥有了所需的一切:

  • SingleTimer::isElapsed真的QTimer::remainingTime() == 0;
  • SingleTimer::set 是真的 QTimer::setSingleShot(true); QTimer::start(time);
  • SingleTimer::slot_setElapsed 变得无用
  • 因此SingleTimer::SingleTimer变得无用,你SingleTimer不再需要一堂课了


nnb*_*nnb 6

使用QTimer用于此目的和利用SIGNALS,并SLOT为开始,并从不同的线程停止定时器/ S的目的.您可以从任何线程发出信号,并在创建计时器的线程中捕获它以对其进行操作.

既然你说你是Qt的新手,我建议你在继续之前先阅读一些教程,这样你才能知道Qt提供什么,并且最终不会试图重新发明轮子.:)

VoidRealms是一个很好的起点.