Unsolved Timer with Lambda function
-
@SPlatten
Since the code looks OK (other than heap issue), try aqDebug()
instead of relying on breakpoint, and move the timeout down to 0 to debug. -
@SPlatten said in Timer with Lambda function:
I have a break point in the lambda slot, it doesn't get hit.
There are only 2 things why slot is not called:
- the thread in which the
QTimer
in living does not have a running event loop - the event loop is locked (by a
QThread::sleep()
or a forever loop)
- the thread in which the
-
I've re-written the code instead of a structure:
class clsMsgTrkr : QTimer { private: static const quint16 mscuint16AckTimeout = 5000; static mmpAck msmpAcks; QJsonObject mobjMsg; clsMsgSender* mpMsgSndr; public: clsMsgTrkr(clsMsgSender* pMsgSndr, const QJsonObject& crobjJSON) { setInterval(mscuint16AckTimeout); mobjMsg = crobjJSON; mpMsgSndr = pMsgSndr; //Add tracker to list clsMsgTrkr::msmpAcks.insert(std::make_pair(clsMsgSender::ulnglngGetMsgID(), this)); QObject::connect(this, &QTimer::timeout, [this]() { qdbg() << "TIMEOUT!"; //Re-send message emit mpMsgSndr->write(mobjMsg); }); start(); } };
I can see in the debugger the constructor is getting called and processed the timer is started but I don't get anything in the slot.
-
@SPlatten Don't know why you are now subclassing QTimer...
You can add a destrcutor with debug output to see whether the instance is destroyed before timeout occurs.
Also check what others wrote. -
-
I added a call after call:
start(); qdbg() << this->isActive();
qdbg is just a macro I use which is:
#define qdbg() qDebug().noquote().nospace()
In the Application Output I see true so the timer is active, but doesn't timeout. Also, I just set the timer interval to 0, still no change, no timeout signal occurs.
-
@SPlatten said in Timer with Lambda function:
In the Application Output I see true so the timer is active, but doesn't timeout. Also, I just set the timer interval to 0, still no change, no timeout signal occurs.
Do you have a forever loop in your code or do you use
QThread::sleep()
?
Are you sureQEventLoop
of the used thread is working? -
@KroMignon, the message transmission is in a thread and there very short sleep in the thread loop:
void clsMsgSender::run() { QJsonObject objJSON; while( blnAnythingToDo(objJSON) == true ) { //Sleep to allow a small cap between transmission QThread::usleep(100); //Look for a module name in the message QJsonObject::iterator itrFound = objJSON.find(clsJSON::mscszMsgType); if ( itrFound != objJSON.end() ) { const QJsonValueRef crobjMsgType = itrFound.value(); QString strMsgType(crobjMsgType.toString()); if ( strMsgType.compare(clsJSON::mscszAck) != 0 ) { //Insert a unique message ID into the message objJSON.insert(clsJSON::mscszMsgID, QString::number(++clsMsgSender::msulnglngMsgID)); //Create entry to monitor status of this message new clsMsgTrkr(this, objJSON); } } //Writes message to socket emit write(objJSON); } emit queueEmpty(); }
-
@SPlatten You expect this to work?
-
@jsulm , ok, perhaps I'm to close to see the obvious, what have I done wrong? Its not complete yet, I haven't finished the code yet, but is there something that would explain why the timer isn't working?
-
@SPlatten I've told you many times to read basic Qt documentation.
this cannot work!!!
First, I suppose clsMsgSender is subclassing
QThread
. And you have create your ownrun()
implementation. So there is no running QEventLoop. This means, all QObject which are running in this thread can NOT receive/emit signals.Second, you have a forever loop, so even if there where a running
QEventLoop
, it will not be called! -
@KroMignon , I'm impatient, I know there is benefit from reading the documentation, I just don't want to stop what I'm doing to spend what would seem a long time to digest the documentation.
-
@SPlatten said in Timer with Lambda function:
I'm impatient,
Perhaps you are impatient, but in fact you are losing days doing nonsense code which not working.
If that is the best way to work, I am pretty sure NO.Reading this document would take you 1 or 2 hours, how many hours have you spend to create those non working code?
-
@SPlatten said in Timer with Lambda function:
I just don't want to stop what I'm doing to spend what would seem a long time to digest the documentation
So, instead you waste your time here?
I really don't get the logic... -
The logic is I was I was hoping this would be quicker...obviously wrong, no worries, I will read the documentation.
-
@SPlatten said in Timer with Lambda function:
The logic is I was I was hoping this would be quicker...obviously wrong, no worries, I will read the documentation.
The point is not to read all Qt documentation, but at least the basics to understand how Qt is working.
There are very basic notion to know.
This will help you to right build your software and to take advantage of Qt architecture.And, as Qt is a asynchronous framework, most of the time you don't have to create threads.
One thing is very important, never look thread this also locks theQEventLoop
and break major Qt feature ==> signals/slots handling. -
@KroMignon , thanks for the advice, I've modified the thread loop to:
void clsMsgSender::run() { QJsonObject objJSON; while( blnAnythingToDo(objJSON) == true ) { //Sleep to allow a small cap between transmission exec(); QThread::usleep(100); //Look for a module name in the message QJsonObject::iterator itrFound = objJSON.find(clsJSON::mscszMsgType); if ( itrFound != objJSON.end() ) { const QJsonValueRef crobjMsgType = itrFound.value(); QString strMsgType(crobjMsgType.toString()); if ( strMsgType.compare(clsJSON::mscszAck) != 0 ) { //Insert a unique message ID into the message objJSON.insert(clsJSON::mscszMsgID, QString::number(++clsMsgSender::msulnglngMsgID)); //Create entry to monitor status of this message new clsMsgTrkr(this, objJSON); } } //Writes message to socket emit write(objJSON); } emit queueEmpty(); }
I've also added a class to replace the original structure:
class clsMsgTrkr { Q_OBJECT private: static const quint16 mscuint16AckTimeout = 5000; static mmpAck msmpAcks; QJsonObject mobjMsg; clsMsgSender* mpMsgSndr; QTimer mtmrMonitor; public: clsMsgTrkr(clsMsgSender* pMsgSndr, QJsonObject& robjJSON); ~clsMsgTrkr(); signals: void startTiming(); public slots: void onStartTiming(); void onTimeout(); };
The implementation:
//Static initialisation mmpAck clsMsgTrkr::msmpAcks; /** * @brief clsMsgTrkr - Class constructor * @param pMsgSndr : Pointer to message sending class * @param robjJSON : Reference to JSON message */ clsMsgTrkr::clsMsgTrkr(clsMsgSender* pMsgSndr, QJsonObject& robjJSON) { mobjMsg = robjJSON; mpMsgSndr = pMsgSndr; //Add tracker to list clsMsgTrkr::msmpAcks.insert(std::make_pair(clsMsgSender::ulnglngGetMsgID(), this)); } /** * @brief clsMsgTrkr::~clsMsgTrkr - Class desctructor */ clsMsgTrkr::~clsMsgTrkr() { if ( mtmrMonitor.isActive() ) { mtmrMonitor.stop(); } } /** * @brief clsMsgTrker::onStartTiming */ void clsMsgTrkr::onStartTiming() { QObject::connect(&mtmrMonitor, &QTimer::timeout, this, &clsMsgTrkr::onTimeout); mtmrMonitor.start(1);//mscuint16AckTimeout); } /** * @brief clsMsgTrkr::onTimeout */ void clsMsgTrkr::onTimeout() { qdbg() << "TIMEOUT!"; //Re-send message emit mpMsgSndr->write(mobjMsg); }
Its still a work in progress, but I'm struggling with the compile errors:
../clsMsgSender.cpp:242:14: note: in instantiation of function template specialization 'QObject::connect<void (QTimer::*)(QTimer::QPrivateSignal), void (clsMsgTrkr::*)()>' requested here QObject::connect(&mtmrMonitor, &QTimer::timeout, this, &clsMsgTrkr::onTimeout);
-
@SPlatten
If I'm not mistaken, you have not pasted the line before (or maybe after) the one you quote, which says what the actual error is..... -
@SPlatten said in Timer with Lambda function:
class clsMsgTrkr {
Q_OBJECTDoes not made sense, do you mean?
class clsMsgTrkr : public QObject { Q_OBJECT ... };
-
@KroMignon thank you, that was the problem I originally based the class on QTimer.