Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Qt timers cannot be stopped from another thread

Hy,

I'm writing my first Qt program and getting now in troubles with:

QObject::killTimer: timers cannot be stopped from another thread

QObject::startTimer: timers cannot be started from another thread

My program will communicate to a CANOpen bus for that I'm using the Canfestival Stack. The Canfestival will work with callback methods. To detects timeout in communication I setup a timer function (somehow like a watchdog). My timer package consist out of a "tmr" module, a "TimerForFWUpgrade" module and a "SingleTimer" module. The "tmr" module was originally C programmed so the static "TimerForFWUpgrade" methods will interface it. The "tmr" module will be part of a C programed Firmware update package.

The timer will work as follows. Before a message is sent I will call TMR_Set method. An then in my idle program loop with TMR_IsElapsed we check for a timer underflow. If TMR_IsElapsed I will do the errorhandling. As you see the TMR_Set method will be called continuously and restart the QTimer again and again.

The above noted errors are appearing if I start my program. Can you tell me if my concept could work? Why does this errors appear? Do I have to use additional threads (QThread) to the main thread?

Thank you

Matt

Run and Idle loop:

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
    ....
}  

Module tmr (interface to C program):

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

INT8 TMR_IsElapsed(UINT8 tmrnbr)
{
 return TimerForFWUpgrade::isElapsed(tmrnbr);
}
}

Module 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;
    }
}

Module 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;
}
like image 702
Matt Avatar asked Oct 20 '14 09:10

Matt


1 Answers

Use QTimer for this purpose and make use of SIGNALS and SLOT for the purpose of starting and stopping the timer/s from different threads. You can emit the signal from any thread and catch it in the thread which created the timer to act on it.

Since you say you are new to Qt, I suggest you go through some tutorials before proceeding so that you will know what Qt has to offer and don't end up trying to reinvent the wheel. :)

VoidRealms is a good starting point.

like image 193
Nithish Avatar answered Sep 22 '22 23:09

Nithish