Help with interrupting Qthreads running infinite loops!
Hi! I have a similar problem to ludoQtCreator's problem where I can't get a signal-slot connection to work in a worker thread when its running a loop, but I tried implementing QCoreApplication::processEvents() and am still having trouble. For context, I am using a stepping motor that oscillates between 2 endpoints in an infinite while loop until asked to stop (currently I use a global variable in the main thread to stop the motion, BUT am unsure if that is the "proper" way to do that - I don't know if there are advantages to calling a function in the worker thread to do so instead). I have other threads / functions that use the exact same global var mechanism to operate, and they work - whereas this one does not. I am trying to interrupt that oscillating motion by destroying the worker thread and then creating a new worker thread. Any help would be suuuuper appreciated. Thanks!!!! I also hit the char limit so please bear with me.
threadController inherits (is this the right term?) information from another QObject called systemHandler. systemHandler houses all the relevant data for the motors (ie motor positions). threadController handles the creation and deletion of threads and runs in the main thread. theadController creates new motorController QObjects and moves them into threads. I made motorController a child of systemHandler because I want to make a "snapshot" of the system's values whenever I direct the program to begin a motor movement - kinda like loading a cassette tape with all the pre-programmed moves into a machine.
threadController.cpp
Code:
#include "threadcontroller.h"
#include "motorcontrollerclasses.h"
#include "serversocket.h"
#include <QObject>
#include <QThread>
#include <QDebug>
threadController
::threadController(System *systemHandler,
QObject *parent
) , m_systemHandler(systemHandler)
{
}
void threadController::startMotorThread() //The "spin" motor thread is an example of the infinite loop in a worker thread that is working for me.
{
qDebug("threadController startMotorThread() called");
stopFlag = 0;
if (m_systemHandler->magnetSpinRate() > 0) {
startSpinThread();
emit userRequestStartSpin();
}
}
void threadController::startSpinThread()
{
qDebug("startSpinThread() called");
spinQThread->setObjectName("spinThread");
motorController *spinMotor = new motorController(*m_systemHandler);
spinMotor->moveToThread(spinQThread);
QObject::connect(spinMotor,
&motorController
::destroyMotorThreadSpin, spinMotor,
&motorController
::deleteLater);
QObject::connect(spinMotor,
&motorController
::destroyMotorThreadSpin, spinQThread,
&QThread
::quit);
QObject::connect(spinQThread,
&QThread
::finished, spinQThread,
&QThread
::deleteLater);
QObject::connect(this,
&threadController
::userRequestStartSpin, spinMotor,
&motorController
::controlSpin);
spinQThread->start();
}
void threadController::stopMotorThread() //stopFlag shuts down ALL of my motors at once - I don't want to use every time for my adjustSweep function (in motorController).
{
stopFlag = 1;
qDebug("threadController stopMotorThread() called");
}
void threadController::startAdjustSweepMotorThread() //the "adjustSweep" is the one I am having trouble with interrupting and destroying the thread.
{
stopAdjustSweepFlag = 0; //stopAdjustSweepFlag is my global var. A value of 1 is supposed to interrupt the sweep. I was noodling around and am using 2 methods to try and stop it - global var and calling a method.
startAdjustSweepThread();
emit startAdjustSweepSignal();
}
void threadController::startAdjustSweepThread()
{
qDebug("startAdjustSweepThread called");
adjustSweepQThread->setObjectName("adjustSweepThread");
motorController *adjustSweepMotor = new motorController(*m_systemHandler); //(m_systemHandler, this);
adjustSweepMotor->moveToThread(adjustSweepQThread);
QObject::connect(this,
&threadController
::threadStopAdjustSweepSignal, adjustSweepMotor,
&motorController
::stopAdjustSweep, Qt
::QueuedConnection);
//This signal is successfully emitted, but the slot is never called! QObject::connect(this,
&threadController
::threadStopAdjustSweepSignal, adjustSweepMotor,
&motorController
::test, Qt
::QueuedConnection);
//Similar story to the above! QObject::connect(adjustSweepMotor,
&motorController
::destroyMotorThreadAdjustSweep, adjustSweepMotor,
&motorController
::deleteLater);
QObject::connect(adjustSweepMotor,
&motorController
::destroyMotorThreadAdjustSweep, adjustSweepQThread,
&QThread
::quit);
QObject::connect(adjustSweepQThread,
&QThread
::finished, adjustSweepQThread,
&QThread
::deleteLater);
QObject::connect(this,
&threadController
::startAdjustSweepSignal, adjustSweepMotor,
&motorController
::adjustSweep, Qt
::QueuedConnection);
//Below is what chatGPT told me to try, I get the signal received statement, but the invokeMethod() doesn't work and can't find the function.
// QObject::connect(this, &threadController::threadStopAdjustSweepSignal, []() {
// qDebug() << "Signal threadStopAdjustSweepSignal received";
// });
//QMetaObject::invokeMethod(adjustSweepMotor, "stopAdjustSweep", Qt::QueuedConnection);
adjustSweepQThread->start();
}
threadController.h
Code:
#ifndef THREADCONTROLLER_H
#define THREADCONTROLLER_H
#include <QObject>
#include "system.h"
class threadController
: public QObject{
Q_OBJECT
public:
explicit threadController
(System *systemHandler,
QObject *parent
= nullptr
);
//explicit threadController(QObject *parent = nullptr);
public slots:
void startMotorThread();
void stopMotorThread();
void stopRotateMotorThread();
void startRotateMotorThreadPrecise();
void startAdjustMotorThread();
void startAdjustSweepMotorThread();
void startSpinThread();
void startRollThread();
void startAdjustThread();
void startAdjustSweepThread();
void startRotateThreadPrecise();
void startInitializeThread();
void startStowThread();
void startStowRotateThread();
void startInitializeRotateThread();
void startInitializeRollThread();
void rollSignalNotifier();
void rotateSignalNotifier();
void rotateStowSignalNotifier();
void stopAdjustRollCalled();
void stopAdjustSweepCalled();
signals:
//void userRequestStart();
void userRequestStartSpin();
void userRequestStartRoll();
void userRequestStartRotatePrecise();
void userRequestStartInitializeRotate();
void userRequestStartInitializeRoll();
void userRequestStartStowRotate();
void startAdjustRollSignal();
void startAdjustSweepSignal();
void threadStopAdjustSweepSignal();
private:
System *m_systemHandler;
};
extern int stopFlag; //This is the stopFlag to initiate stopping of the motors.
extern int stopRotate; //StopFlag to stop rotate motors.
extern int stopSpinFlag;
extern int stopRollFlag;
extern int stopAdjustRollFlag; //stopFlag to end the adjust movement
extern int stopAdjustSweepFlag; //stopFlag to end sweep movement.
#endif // THREADCONTROLLER_H
Re: Help with interrupting Qthreads running infinite loops!
Without too much study of your code, one thing I notice is that each time you create a new "motorController" instance you are passing "*m_systemHandler". This is creating a copy of the System instance pointed to by m_systemHandler, meaning each motorController instance has its own unique System instance, not a pointer to what I think you want as the main System instance passed to the threadController constructor.
Re: Help with interrupting Qthreads running infinite loops!
Hi sorry! I actually figured it out! I just needed to add Q_INVOKABLE in front of the function that wasn't working. I also realized I should have boiled the code down into something a bit more understandable haha.