Problem with running timer in another thread
-
@Damian7546 print out thread ids on the screen in the constructor and in this function. Check out why they are different.
@hskoglund without changes.
QML debugging is enabled. Only use this in a safe environment.
ThreadID SerialWorker: 0x7cb34f9b27c0
ThreadID CctalkLinkController: 0x7cb34f9b27c0
ThreadID CctalkDevice: 0x7cb34f9b27c0
ThreadID MyCcTalkApp: 0x7cb34f9b27c0
LogMessgae: "* Coin acceptor configured device: /dev/ttyUSB0"
LogMessgae: "* Opening port "/dev/ttyUSB0"."
LogMessgae: "Requested device state change from ShutDown to: Initialized"
ThreadID in startTimer() 0x71df85200640
LogMessgae: "* Port "/dev/ttyUSB0" opened."
LogMessgae: "> ccTalk request: SimplePoll, address: 2, data: (empty)"
QMetaObject::invokeMethod: No such method qtcc::CctalkDevice::startTimer()
LogMessgae: "> Request: 020001feff"
LogMessgae: "< Full response: 020001feff01000200fd"
LogMessgae: "< ccTalk response from address 2, data: (empty)"
LogMessgae: "* Device is alive (answered to simple poll)"
QObject::startTimer: Timers cannot be started from another thread*now I don't understand anything, why only the startTimer is on other thread?
-
@hskoglund without changes.
QML debugging is enabled. Only use this in a safe environment.
ThreadID SerialWorker: 0x7cb34f9b27c0
ThreadID CctalkLinkController: 0x7cb34f9b27c0
ThreadID CctalkDevice: 0x7cb34f9b27c0
ThreadID MyCcTalkApp: 0x7cb34f9b27c0
LogMessgae: "* Coin acceptor configured device: /dev/ttyUSB0"
LogMessgae: "* Opening port "/dev/ttyUSB0"."
LogMessgae: "Requested device state change from ShutDown to: Initialized"
ThreadID in startTimer() 0x71df85200640
LogMessgae: "* Port "/dev/ttyUSB0" opened."
LogMessgae: "> ccTalk request: SimplePoll, address: 2, data: (empty)"
QMetaObject::invokeMethod: No such method qtcc::CctalkDevice::startTimer()
LogMessgae: "> Request: 020001feff"
LogMessgae: "< Full response: 020001feff01000200fd"
LogMessgae: "< ccTalk response from address 2, data: (empty)"
LogMessgae: "* Device is alive (answered to simple poll)"
QObject::startTimer: Timers cannot be started from another thread*now I don't understand anything, why only the startTimer is on other thread?
@Damian7546 move startTimer() to public slots:
public slots:
void startTimer();if ( QThread::currentThread() != thread() ) { metaObject()->invokeMethod( this, "startTimer", Qt::QueuedConnection ); return; }If you have stop func for timer, you may need to do the same thing. The code above works in my app.
-
@Damian7546 move startTimer() to public slots:
public slots:
void startTimer();if ( QThread::currentThread() != thread() ) { metaObject()->invokeMethod( this, "startTimer", Qt::QueuedConnection ); return; }If you have stop func for timer, you may need to do the same thing. The code above works in my app.
@JoeCFD something is starting to work...
-
@JoeCFD something is starting to work...
@Damian7546 Have fun.
-
@Damian7546 Have fun.
@hskoglund said in Problem with running timer in another thread:
Ah, I see in your cctalk_device.h file, startTimer() is declared under protected:
try moving it under slots: (like your function void timerIteration();)Problem is more complicated then can I thought, probably not related with startTimer() function .
I totally remove calling startTimer() from my project and still have the same error :QML debugging is enabled. Only use this in a safe environment. ThreadID SerialWorker: 0x79e36d8867c0 ThreadID CctalkLinkController: 0x79e36d8867c0 ThreadID CctalkDevice: 0x79e36d8867c0 Using "/home/developer/.config/CCtalkProj.ini" as a user-specific settings file ThreadID MyCcTalkApp: 0x79e36d8867c0 "* Coin acceptor configured device: /dev/ttyUSB0" "* Opening port \"/dev/ttyUSB0\"." "Requested device state change from ShutDown to: Initialized" test test test "* Port \"/dev/ttyUSB0\" opened." "> ccTalk request: SimplePoll, address: 2, data: (empty)" "> Request: 020001feff" "< Full response: 020001feff01000200fd" "< ccTalk response from address 2, data: (empty)" "* Device is alive (answered to simple poll)" QObject::startTimer: Timers cannot be started from another threadBelow I publish code wihich I try run:
[https://github.com/ienecode/cctalk.git](link url) -
Still the same problem as originally.
your 'serial_port_' is not moved with move ToThread QSerialPort uses internally QTimer thats why you see the message.
-
@J-Hilk So, how can I fix this code ? Can you give me tips ?
-
Pass the correct parent to your timer.
-
@J-Hilk So, how can I fix this code ? Can you give me tips ?
- Fix your constructor of your QObject based worker: More of a principal matter in this case
class SerialWorker : public QObject { Q_OBJECT public: /// Constructor SerialWorker(); ...->... class SerialWorker : public QObject { Q_OBJECT public: /// Constructor explicit SerialWorker(QObbject *parent = nullptr); ..... SerialWorker::SerialWorker() { ...->... SerialWorker::SerialWorker(QObject*parent) : QObject(parent) {- Drop the scoped pointer, you're trying to be fancy when there's no need for it and it's causing trouble
QScopedPointer<QSerialPort> serial_port_; ...-> QSerialPort * const serial_port_; //Raw dogging the serial port, hell ya- Init the QSerialport correctly:
SerialWorker::SerialWorker(QObject*parent) : QObject(parent), serial_port_{new QSerialPort(this)} { -
- Fix your constructor of your QObject based worker: More of a principal matter in this case
class SerialWorker : public QObject { Q_OBJECT public: /// Constructor SerialWorker(); ...->... class SerialWorker : public QObject { Q_OBJECT public: /// Constructor explicit SerialWorker(QObbject *parent = nullptr); ..... SerialWorker::SerialWorker() { ...->... SerialWorker::SerialWorker(QObject*parent) : QObject(parent) {- Drop the scoped pointer, you're trying to be fancy when there's no need for it and it's causing trouble
QScopedPointer<QSerialPort> serial_port_; ...-> QSerialPort * const serial_port_; //Raw dogging the serial port, hell ya- Init the QSerialport correctly:
SerialWorker::SerialWorker(QObject*parent) : QObject(parent), serial_port_{new QSerialPort(this)} {@J-Hilk said in Problem with running timer in another thread:
Fix your constructor of your QObject based worker: More of a principal matter in this case
Drop the scoped pointer, you're trying to be fancy when there's no need for it and it's causing trouble
Init the QSerialport correctly:
TBH these things are also "weird" / designed badly in the original repository, @Damian7546 just copied/forked this structure.
I'm wondering if any of the original stuff actually works... from looking at it I would say it also has many issues.
Usually just including the class inQObject's parent-child structure and therefore moving the thread affinity with the parent would fix this. That's what I wrote/thought earlier, but it seems that this is not so easy to do due to the way the whole thing is designed.QSerialPort * const serial_port_; //Raw dogging the serial port, hell yaLMAO :D
-
@J-Hilk After changes proposed by you , the logs are this:
"* Coin acceptor configured device: /dev/ttyUSB0" "* Opening port \"/dev/ttyUSB0\"." "Requested device state change from ShutDown to: Initialized" "* Port \"/dev/ttyUSB0\" opened." "> ccTalk request: SimplePoll, address: 2, data: (empty)" "Starting poll timer." "> Request: 020001feff" "Polling......" "< Full response: 020001feff01000200fd" "< ccTalk response from address 2, data: (empty)" "* Device is alive (answered to simple poll)" QObject::startTimer: Timers cannot be started from another thread "Polling......" "Polling......" "Polling......" "- The last message was repeated 40 times total" "- The last message was repeated 80 times total" "- The last message was repeated 120 times total" "- The last message was repeated 160 times total" -
@J-Hilk After changes proposed by you , the logs are this:
"* Coin acceptor configured device: /dev/ttyUSB0" "* Opening port \"/dev/ttyUSB0\"." "Requested device state change from ShutDown to: Initialized" "* Port \"/dev/ttyUSB0\" opened." "> ccTalk request: SimplePoll, address: 2, data: (empty)" "Starting poll timer." "> Request: 020001feff" "Polling......" "< Full response: 020001feff01000200fd" "< ccTalk response from address 2, data: (empty)" "* Device is alive (answered to simple poll)" QObject::startTimer: Timers cannot be started from another thread "Polling......" "Polling......" "Polling......" "- The last message was repeated 40 times total" "- The last message was repeated 80 times total" "- The last message was repeated 120 times total" "- The last message was repeated 160 times total"@Damian7546
At this point I doubt that anyone can reliably know what exactly your code reads. You clearly still have a thread issue.I am unsure: have you identified where the
startTimer()call is issued from in code? -
@J-Hilk After changes proposed by you , the logs are this:
"* Coin acceptor configured device: /dev/ttyUSB0" "* Opening port \"/dev/ttyUSB0\"." "Requested device state change from ShutDown to: Initialized" "* Port \"/dev/ttyUSB0\" opened." "> ccTalk request: SimplePoll, address: 2, data: (empty)" "Starting poll timer." "> Request: 020001feff" "Polling......" "< Full response: 020001feff01000200fd" "< ccTalk response from address 2, data: (empty)" "* Device is alive (answered to simple poll)" QObject::startTimer: Timers cannot be started from another thread "Polling......" "Polling......" "Polling......" "- The last message was repeated 40 times total" "- The last message was repeated 80 times total" "- The last message was repeated 120 times total" "- The last message was repeated 160 times total"Since you probably used the code from the original GitHub repo without modifying it, you should reach out to the owner of the repo via GitHub issues.
Maybe he can identify the problem as a whole faster than a bunch of people in the forum here, who have to dive into the project first and dig through the logic to understand how everything is put together.
As @J-Hilk mentioned above, there are a couple of things that could have been done cleaner...
(creating QObject derived worker without actually calling the QObject base implementation... etc...) -
@JonB
My opinion it call only once, in the CctalkDevice::requestSwitchDeviceState (cctalk_device.cpp) , when the device goes to Initialized.
241 linie:https://github.com/ienecode/cctalk/blob/main/cctalk/cctalk_device.cpp@Pl45m4
I contacted the author, and he tells me that this code was developed for a project that was stopped before there was a chance to properly test the code,
so this is the state it was left in.I interesed in this code, because I think that the structure of this code for SERIAL communication seems very reasonable and developmental to me.
So I would be really grateful if anyone of forumers could be help me run this code , especially to run cyclic polling , in way is realized in this code.
-
I don't see a reason to use threads for simple serial communication with QSerialPort at all. It just complicates things, esp. for people without proper knowledge about threads. Don't use it - simply use QSerialPort and proper signals & slots.
-
@Christian-Ehrlicher I expected such answers: "simply use QSerialPort and proper signals & slots." . I have project realized in this way.
But as part of learning (main goal of the project) programming and uing threads I would like to use threads this time to serial communication, and run example considered in this topic. -
@Christian-Ehrlicher I expected such answers: "simply use QSerialPort and proper signals & slots." . I have project realized in this way.
But as part of learning (main goal of the project) programming and uing threads I would like to use threads this time to serial communication, and run example considered in this topic.@Damian7546
Then by choosing to use threads where they are probably not needed you (or the original author) have ended up with a problem using threads, possibly because the original code was not well written for threads. Which tells you a lot... ! Just saying. -
@Christian-Ehrlicher I expected such answers: "simply use QSerialPort and proper signals & slots." . I have project realized in this way.
But as part of learning (main goal of the project) programming and uing threads I would like to use threads this time to serial communication, and run example considered in this topic.@Damian7546 said in Problem with running timer in another thread:
But as part of learning (main goal of the project) programming and uing threads I would like to use threads this time to serial communication, and run example considered in this topic.
Then you can look, for example, at Qt's Blocking Serial Port Examples:
(Sender)
(Receiver)
Or you use some non-Qt implementation of serial port communication, such as
serial_portfromBoost.ASIOlibrary.
(makes little sense, since you are already using Qt which provides all that stuff... but for learning purposes it's fine to look at different techniques)