Qt timers cannot be stopped from another thread

Hy

I am writing my first Qt program and am now experiencing problems:

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

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

My program will communicate with the CANOpen bus because I use the Canfestival Stack . Canfestival will work with callback methods. To detect a timeout in communication, I set up a timer function (kind of like a watchdog). My timer package consists of the tmr module, the TimerForFWUpgrade module, and the SingleTimer module. The tmr module was originally programmed in C, so the static methods of TimerForFWUpgrade will interact with it. The tmr module will be part of the C firmware update package.

The timer will work as follows. Before sending the message, I will call the TMR_Set method. Then, in my idle program cycle with TMR_IsElapsed, we check the lower flow of the timer. If TMR_IsElapsed, I will do error handling. As you can see, the TMR_Set method will be called continuously and run QTimer again and again.

The above errors appear if I run my program. Can you tell me if my concept can work? Why do these errors appear? Should I use additional threads (QThread) for the main thread?

thanks

Matt

Startup and wait 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 .... } 

Tmr module (interface to program C):

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

TimerForFWUpgrade module:

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

SingleTimer Module:

 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; } 
+8
c ++ multithreading qt qthread qtimer
source share
3 answers

Use QTimer for this purpose and use SIGNALS and SLOT to start and stop the timer / sec from different threads. You can emit a signal from any stream and catch it in the stream that the timer created to act on it.

Since you say that you are new to Qt, I suggest you go through some tutorials before continuing so you know what Qt has to offer and don’t try to invent a wheel. :)

VoidRealms is a good starting point.

+6
source share

You have this problem because timers in a static array are created in Thread X , but they start and stop in Thread Y This is not allowed since Qt relies on binding the thread to time-timers.

You can either create, start a stop in the same thread, or use the signal and slots to start the start and stop operations for timers. The signal and slot solution is a bit problematic because you have n QTimer objects (hint: how to start a timer at position i ?)

Instead, you can create and initialize a timer at tmrnbr position in

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

which is executed by the same thread.

In addition, you do not need the SingleTimer class. You are using Qt5, and you already have everything you need:

  • SingleTimer::isElapsed really QTimer::remainingTime() == 0 ;
  • SingleTimer::set really QTimer::setSingleShot(true); QTimer::start(time); QTimer::setSingleShot(true); QTimer::start(time);
  • SingleTimer::slot_setElapsed becomes useless
  • Thus, SingleTimer::SingleTimer becomes useless and you no longer need the SingleTimer class
+5
source share

I got errors after changing the timer concept. I will no longer use my SingleTimer module. I will not allow a timeout before QTimer and, possibly, because of this I am having problems. Now I have a cyclic QTimer that plays out every 100 ms in the slot function. Then I count events. Below is my working code:

 TimerForFWUpgrade::TimerForFWUpgrade(QObject* parent) : QObject(parent), pTime(new QTimer(this)) { connect(pTime, SIGNAL(timeout()), this, SLOT(slot_handleTimer())); pTime->setTimerType(Qt::PreciseTimer); pTime->start(100); } void TimerForFWUpgrade::set(unsigned char tmrnbr, unsigned int time) { if(tmrnbr < NR_OF_TIMERS) { if(timeBase != 0) { myTimeout[tmrnbr] = time / timeBase; } else { myTimeout[tmrnbr] = 0; } myTimer[tmrnbr] = 0; myElapsed[tmrnbr] = false; myActive[tmrnbr] = true; } } char TimerForFWUpgrade::isElapsed(unsigned char tmrnbr) { QCoreApplication::processEvents(); if(tmrnbr < NR_OF_TIMERS) { if(true == myElapsed[tmrnbr]) { return 1; } else { return 0; } } else { return 0; // NOK } } void TimerForFWUpgrade::slot_handleTimer() { for(UINT8 i = 0; i < NR_OF_TIMERS; i++) { if(myActive[i] == true) { myTimer[i]++; if(myTimeout[i] < myTimer[i]) { myTimer[i] = 0; myElapsed[i] = true; myActive[i] = false; } } } } 
0
source share

All Articles