I have a class in the main thread which initiates another thread. From the created thread, I send a signal to main thread to get the current documentElement of the QWebView and main thread replies to to the thread and sets the local QWebElement variable in the thread. So, here is some code:
Thread has:
...
public slots:
void setCurrentElement(QWebElement aElement);
signals:
void sgGetCurrentElement(void);
private:
QWebElement currentElement;
Main thread has:
...
public slots:
void onGetCurrentElementReceived(void);
signals:
void sgResponseToGetElement(QWebElement aElement);
After creating the thread, I connect the signals to slots like:
connect(insExtractor, SIGNAL(sgGetCurrentElement()), this, SLOT(onGetCurrentElementReceived()));
connect(this, SIGNAL(sgResponseToGetElement(QWebElement)), insExtractor, SLOT(setCurrentElement(QWebElement)));
Once the main thread receives a signal from the thread, it does the following:
void targetClass::onGetCurrentElementReceived(void)
{
emit sgResponseToGetElement(insWebView->page()->mainFrame()->documentElement());
}
The setter in the thread does the following:
void createdThread::setCurrentElement(QWebElement aElement)
{
currentElement = aElement;
}
Here is the problem:
My target is to find the first form element whose id is submitForm. There is such a form in the element, no problem there.
If I write the following line before emitting the signal in the main thread:
QWebElement form_found = currentElement.findFirst("form[id='submitForm']");
form_found doesn't return null and it finds the form element. No problem.
If I write the same code right after I set the currentElement in setCurrentElement in the thread, it does the same and it finds the form. However, if I do the same right after I emit the very first signal again in the thread, it returns null. Here is the code:
void createdThread::startExtracting(void)
{
sgGetCurrentElement();
QThread::msleep(2000);
QWebElement form_found = currentElement.findFirst("form[id='submitForm']");
}
So, form_found is coming null. Could anyone tell me why it is returning null? I put logs everywhere and it is being called after it is set in the setter. What is wrong with this?
My suspect is that you are stopping the event loop of the thread doing the sleep.
Threads in Qt are a bit tricky. Take a look at this, it makes all these questions very clear.
I'd say you should use the Element when you are sure you got it and that's on setCurrentElement. Why don't you start the extraction on that method ?
Related
I work in Qt and when I press the button GO I need to continuously send packages to the network and modify the interface with the information I receive.
The problem is that I have a while(1) in the button so the button never finishes so the interface is never updated. I thought to create a thread in the button and put the while(){} code there.
My question is how can I modify the interface from the thread? (For example how can I modify a textBox from the thread ?
Important thing about Qt is that you must work with Qt GUI only from GUI thread, that is main thread.
That's why the proper way to do this is to notify main thread from worker, and the code in main thread will actually update text box, progress bar or something else.
The best way to do this, I think, is use QThread instead of posix thread, and use Qt signals for communicating between threads. This will be your worker, a replacer of thread_func:
class WorkerThread : public QThread {
void run() {
while(1) {
// ... hard work
// Now want to notify main thread:
emit progressChanged("Some info");
}
}
// Define signal:
signals:
void progressChanged(QString info);
};
In your widget, define a slot with same prototype as signal in .h:
class MyWidget : public QWidget {
// Your gui code
// Define slot:
public slots:
void onProgressChanged(QString info);
};
In .cpp implement this function:
void MyWidget::onProgressChanged(QString info) {
// Processing code
textBox->setText("Latest info: " + info);
}
Now in that place where you want to spawn a thread (on button click):
void MyWidget::startWorkInAThread() {
// Create an instance of your woker
WorkerThread *workerThread = new WorkerThread;
// Connect our signal and slot
connect(workerThread, SIGNAL(progressChanged(QString)),
SLOT(onProgressChanged(QString)));
// Setup callback for cleanup when it finishes
connect(workerThread, SIGNAL(finished()),
workerThread, SLOT(deleteLater()));
// Run, Forest, run!
workerThread->start(); // This invokes WorkerThread::run in a new thread
}
After you connect signal and slot, emiting slot with emit progressChanged(...) in worker thread will send message to main thread and main thread will call the slot that is connected to that signal, onProgressChanged here.
P.s. I haven't tested the code yet so feel free to suggest an edit if I'm wrong somewhere
So the mechanism is that you cannot modify widgets from inside of a thread otherwise the application will crash with errors like:
QObject::connect: Cannot queue arguments of type 'QTextBlock'
(Make sure 'QTextBlock' is registered using qRegisterMetaType().)
QObject::connect: Cannot queue arguments of type 'QTextCursor'
(Make sure 'QTextCursor' is registered using qRegisterMetaType().)
Segmentation fault
To get around this, you need to encapsulate the threaded work in a class, like:
class RunThread:public QThread{
Q_OBJECT
public:
void run();
signals:
void resultReady(QString Input);
};
Where run() contains all the work you want to do.
In your parent class you will have a calling function generating data and a QT widget updating function:
class DevTab:public QWidget{
public:
void ThreadedRunCommand();
void DisplayData(QString Input);
...
}
Then to call into the thread you'll connect some slots, this
void DevTab::ThreadedRunCommand(){
RunThread *workerThread = new RunThread();
connect(workerThread, &RunThread::resultReady, this, &DevTab::UpdateScreen);
connect(workerThread, &RunThread::finished, workerThread, &QObject::deleteLater);
workerThread->start();
}
The connection function takes 4 parameters, parameter 1 is cause class, parameter 2 is signal within that class. Parameter 3 is class of callback function, parameter 4 is callback function within the class.
Then you'd have a function in your child thread to generate data:
void RunThread::run(){
QString Output="Hello world";
while(1){
emit resultReady(Output);
sleep(5);
}
}
Then you'd have a callback in your parent function to update the widget:
void DevTab::UpdateScreen(QString Input){
DevTab::OutputLogs->append(Input);
}
Then when you run it, the widget in the parent will update each time the emit macro is called in the thread. If the connect functions are configured properly, it will automatically take the parameter emitted, and stash it into the input parameter of your callback function.
How this works:
We initialise the class
We setup the slots to handle what happens with the thread finishes and what to do with the "returned" aka emitted data because we can't return data from a thread in the usual way
we then we run the thread with a ->start() call (which is hard coded into QThread), and QT looks for the hard coded name .run() memberfunction in the class
Each time the emit resultReady macro is called in the child thread, it's stashed the QString data into some shared data area stuck in limbo between threads
QT detects that resultReady has triggered and it signals your function, UpdateScreen(QString ) to accept the QString emitted from run() as an actual function parameter in the parent thread.
This repeats every time the emit keyword is triggered.
Essentially the connect() functions are an interface between the child and parent threads so that data can travel back and forth.
Note: resultReady() does not need to be defined. Think of it as like a macro existing within QT internals.
you can use invokeMethod() or Signals and slots mechanism ,Basically there are lot of examples like how to emit a signal and how to receive that in a SLOT .But ,InvokeMethod seems interesting .
Below is example ,where it shows How to change the text of a label from a thread:
//file1.cpp
QObject *obj = NULL; //global
QLabel *label = new QLabel("test");
obj = label; //Keep this as global and assign this once in constructor.
Next in your WorkerThread you can do as below:
//file2.cpp (ie.,thread)
extern QObject *obj;
void workerThread::run()
{
for(int i = 0; i<10 ;i++
{
QMetaObject::invokeMethod(obj, "setText",
Q_ARG(QString,QString::number(i)));
}
emit finished();
}
you start thread passing some pointer to thread function (in posix the thread function have the signature void* (thread_func)(void*), something equal under windows too) - and you are completely free to send the pointer to your own data (struct or something) and use this from the thread function (casting pointer to proper type). well, memory management should be though out (so you neither leak memory nor use already freed memory from the thread), but this is a different issue
I am using QThread for some huge task in background, here is sample
code i am using
class Worker : public QObject
{
Q_OBJECT
QThread workerThread;
public slots:
void doWork(const QString ¶meter) {
while(1){
// some huge code here
......................
if(condition) break;
}
emit resultReady(result);
}
signals:
void resultReady(const QString &result);
};
class Controller : public QObject
{
Q_OBJECT
QThread workerThread;
public:
Controller() {
Worker *worker = new Worker;
worker->moveToThread(&workerThread);
connect(&workerThread, SIGNAL(finished()), worker, SLOT(deleteLater()));
connect(this, SIGNAL(operate(QString)), worker, SLOT(doWork(QString)));
connect(worker, SIGNAL(resultReady(QString)), this, SLOT(handleResults(QString)));
workerThread.start();
}
~Controller() {
workerThread.quit();
workerThread.wait();
}
public slots:
void handleResults(const QString &);
signals:
void operate(const QString &);
};
Is it recommended to use wait() after quit in above program?
My program sometimes stuck on QThread::wait(), it is downloading huge file from server and it take about 5-6 min to again check for while condition , I just want to exit from thread but main thread stuck at wait(), is there any way?? to exit or kill thread forcefully without crash or hang main application? I also tried QThread::terminated but it never works.
Any Help appreciated.
Thanks.
First of all it is not clear what you are doing at your thread from your above codes. Your first point of concentration is your method which is running inside your thread i.e. your thread object. First of all, why sometime your thread does not complete its task? and why it stuck? Here I can see a while loop with a condition always true. Probably you have some break statement inside the loop which sometimes never satisfy and because of that thread never complete as while loop is continuing. Just check closely what going wrong there. If while loop is creating the issue I can advice you with the following modification in your code. But you must be very careful because it should not exit before completing some very important task.
First modify your while loop like below:-
introduce one bool variable before the while loop
bool continued = true;
while(continued)
{
//your codes
}
Now add one method in your thread object Worker
void stopWorker()
{
continued = false;
}
Now just call this method when you want your thread to exit by force
worker->stopWorker();
Since Qt 5.2 there is a QThread::requestInterruption() this function alone that can e used to signal to your thread that it should stop working, however you MUST check in you long operation for QThread::isInterruptionRequested() and quit your loop or event loop:
http://doc.qt.io/qt-5/qthread.html#isInterruptionRequested
Official documentation for QThread class says:
bool QThread::wait(unsigned long time = ULONG_MAX)
Blocks the thread until either of these conditions is met:
The thread associated with this QThread object has finished execution (i.e. when it returns from run()). This function will return true if the thread has finished. It also returns true if the thread has not been started yet.
time milliseconds has elapsed. If time is ULONG_MAX (the default), then the wait will never timeout (the thread must return from run()). This function will return false if the wait timed out.
As you can see, ULONG_MAX is the default parameter for the method, and it forces the method to never timeout.
Is it a choice to add your own timeout in the method parameter?
I'm trying to update the main window by calling updateGUI function in a thread every 500 ms. The window is displayed but not updated with the new values unless I close the window. When I do so, a new window is opened with the new value. I found this question but it didn't answer my question. I knew that (as stated in qt documentation)
QApplication::exec enters the main event loop and waits until
exit() is called.
I tried to use processEvents() but the main window is opened and closed repeatedly and very fast that I can't even see it. Here is my code:
float distanceToObject;
bool objectDetected;
Modes currentMode;
void timerStart(std::function<void(void)> func, unsigned int interval)
{
std::thread([func, interval]()
{
while (true)
{
auto x = std::chrono::steady_clock::now() + std::chrono::milliseconds(interval);
func();
std::this_thread::sleep_until(x);
}
}).detach();
}
int updateGUI(void)
{
int argc = 0;
char **argv = NULL;
QApplication a(argc, argv);
MainWindow w;
// Set text of a label
w.setDistance(QString::number(distanceToObject));
// Also update objectDetected and currentMode values
w.show();
//a.processEvents();
return a.exec();
}
void sendMsg(void)
{
// Send heartbeat signal to another device
}
void receiveMsg(void)
{
// Read messages from the other device and update the variables
// These two values change continuously
objectDetected = true;
distanceToObject = 5.4;
}
void decide(void)
{
// The core function of the program. Takes relatively long time
// Run a decision-making algorithm which makes decisions based on the values received from the other device.
// Update some variables according to the made decisions
currentMode = Auto;
// Execute functions according to the made decisions.
setMode(currentMode);
}
int main(void)
{
timerStart(updateGUI, 500);
timerStart(sendMsg, 1000);
timerStart(receiveMsg, 10);
timerStart(decide, 500);
}
How can I update the main window with the variables' values correctly?
Your thread does not update the MainWindow, but it does create an entirely new QApplication and MainWindow on every iteration. Your thread should be stuck inside QApplication::exec until you quit the application (e.g. by closing the window). Only then should your thread's loop make further progress.
In general, you must be very careful when doing updates from outside the main thread, since typically GUI operations must be performed inside the main thread.
Think about using QThread, which already comes with its own event loop, which you can use to notify/update your window using a respective slot.
Without further details about what you are actually trying to achieve, it is not possible to give you further direction. I, at least, recommend that you create your QApplication and MainWindow inside the main thread (e.g. main). Then it depends what you are trying to 'update'. If you need to progress some data, then you can do that within your second thread and send the results to your MainWindow instance using signal-slot. If you need to draw onto the window, then this either has to be done in the main thread directly, or you might find a way to render into a separate buffer (i.e. QImage) from within your thread and then send this buffer to the main thread for drawing it into the window.
I try to sketch how something like this can be done. Notice, however, that this it neither complete nor compilable, but merely an outline.
First, you have your MainWindow and add to it a signal, that notifies all observers to start doing their work (will become clear in a moment). Furthermore, you add slots that will be invoked whenever one of your values changes. Those slots run in the main thread (and are members of the MainWindow) and thus can update the window however they need to:
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
// constructors and stuff
void startWorking()
{
emit startWorkers();
}
public slots:
void onModeChanged(Modes m)
{
// update your window with new mode
}
void onDistanceChanged(float distance)
{
// update your window with new distance
}
signals:
void startWorkers();
};
Next, you build a Worker class, that encapsulates all the 'background work' you like to do (basically what your thread did in your original code):
class Worker : public QObject
{
Q_OBJECT
public:
// constructors and stuff
public slots:
void doWork()
{
while(!done)
{
// do stuff ...
Modes m = // change mode
emit modeModified(m);
// do stuff ...
float distance = // compute distance
emit distanceModified(distance);
// do stuff ...
}
}
signals:
void modeModified(Modes m);
void distanceModified(float distance);
};
Note, that Worker must inherit QObject and that your doWork method must be a public slot. Furthermore, you add a signal for each of the values you like your MainWindow to be informed about. No implementation for them is needed, since it is generated by the Qt MOC (Meta Object Compiler). Whenever one of the respective values changes, simply emit the corresponding signal and pass the new value.
Lastly, you put everything together:
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
MainWindow window;
// create a worker object
Worker* worker = new Worker;
// connect signals and slots between worker and main window
QObject::connect(worker, &Worker::modeModified,
&window, &MainWindow::onModeChanged);
QObject::connect(worker, &Worker::distanceModified,
&window, &MainWindow::onDistanceChanged);
QObject::connect(&window, &MainWindow::startWorkers,
worker, &Worker::doWork);
// create a new thread
QThread* thread = new QThread;
// send worker to work inside this new thread
worker->moveToThread(thread);
thread->start();
// show window and start doing work
window.show();
window.startWorking();
// start main loop
int result = app.exec();
// join worker thread and perform cleanup
return result;
}
Alright, let's go through it. First, you create your QApplication and MainWindow inside your main thread. Next, create an instance of your Worker object (could create multiple here). Then you connect the signals of the worker to the slots of the window and vice versa. Once these connections are established, whenever you emit a signal, the connected slot is invoked by Qt (and passed values are transmitted). Notice, that this connection works across thread boundaries. Whenever a signal is emitted from a thread different then the receiving object's thread, Qt will send a message, which is processed in the receiving object's thread.
Then you tell Qt that you want your worker to live inside another thread using QObject::moveToThread. See here for a very detailed explanation of how to correctly use QThread and objects inside it.
The rest is then simple. show your window and start processing. Here different ways are possible. I just call the startWorking method here, which then emits the startWorkers signal, which is connect to the worker's doWork method, such that doWork will start executing after this signal is received by the other thread.
You then call QApplication::exec which runs the main thread's event loop, where all these signals are processed by Qt. Once your application is closed (e.g. by calling quit or closing the main window) the exec method returns and you are back in main. Notice, that you need to correctly close the thread (e.g. by sending an addition signal that stops the while loop) and join it. You also should delete all the allocated objects (worker, thread). I omitted this here for simplicity of the code example.
Answering your Question
I have many functions, e.g., updateClips and mavReceive that should be called periodically and run independently from each other. I should create a different Worker class for each function, as each has different signals, and a QThread object for each of these functions, right? I don't need startTimer() anymore? If yes, how can I control the calling interval for each function (used to be done in startTimer()
from the comment:
The answer greatly depends on what exactly you mean by "should be called periodically". Who is supposed to call them? The user? Or should they just be executed periodically?
So in principle, you can have multiple workers in one thread. However, if they are supposed to do work all the time (spin in a while loop) it does not make sense, since one is running and all others are blocked. In that case you would have one thread for each worker.
If I understand you correctly, you are interested in updating something periodically (e.g. every 500ms). In that case I highly recommend using the QTimer. You can set an interval and then start it. The timer will then periodically emit the timeout signal, which you can connect to whatever function (more precisely slot) you want to have executed.
An updated version of the Worker could look like this:
class Worker : public QObject
{
Q_OBJECT
public:
Worker()
{
QObject::connect(&modeTimer_, &QTimer::timeout,
this, &Worker::onModeTimerTimeout);
QObject::connect(&distanceTimer_, &QTimer::timeout,
this, &Worker::onDistanceTimerTimeout);
modeTimer_.start(500); // emit timeout() every 500ms
distanceTimer_.start(100); // emit timeout() every 100ms
}
public slots:
void onModeTimerTimeout()
{
// recompute mode
Modes m = // ...
emit modeModified(m);
}
void onDistanceTimerTimeout()
{
// recompute distance
float distance = // ...
emit distanceModified(distance);
}
signals:
void modeModified(Modes m);
void distanceModified(float distance);
private:
QTimer modeTimer_;
QTimer distanceTimer_;
};
Notice, the connections established in the constructor. Whenever one of the timers times out, the connected slot is invoked. This slot then may compute whatever it needs to and afterwards send the result back to the MainWindow in the main thread using the same signal as before.
So, as you see, you can have multiple timers / re-computations / update signals within one Worker (and thus, one thread). However, the crucial point for an implementation is, how long the computations take. If they take very long (e.g. nearly as long as the intervals) then you should think about using multiple threads to speed up the computation (meaning: perform one computation in each thread). As I slowly seem to get a clearer picture of what you want to achieve, I am wondering whether it is only about these periodic updates that you 'misused' the thread for in your question. If this is indeed the case, then you do not need that thread and Worker at all. Then simply add the timers to your MainWindow and connect their timeout signal to the respective slot of the MainWindow directly.
Structure Of Application:
MainWindow -> ProcessingThread(QThread) - > QProcess for Python Script
In the Run/Exec loop of Processing Thread I would like to interact with the process.
How do I go about it?
Current Problem:
I know both ProcessingThread(QThread) and its Run loop run inside different threads. Hence if I initialize the QProcess in QThread constructor I am unable to interact with the process because of following error:
QSocketNotifier: Socket Notifiers cannot be enabled or disabled from
another thread
and if I try to initialize the process in the Run Loop I get the following error:
QObject: Cannot create children for a parent that is in a different
thread
(Parent is ProcessingThread(0x984b2a0), parent's thread is QThread(0x940e180)),
current thread is ProcessingThread(0x984b2a0)
If I initialize the QProcess in ProcessingThread constructor, I am able to interact with the script perfectly.
Any suggestions?
Update: Also The reason for using QThread is because I am performing image processing, the Processing Threads keeps fetching images from camera. Some of these images need to be further processed by the Python script running in QProcess.
Update 2: CODE
void MainWindow::MainWindow(QWidget *parent)
{
...
debugProcessingThread = new DebugProcessingThread();
}
class DebugProcessingThread : public QThread
{
Q_OBJECT
...
private:
qProcess *myprocess;
}
DebugProcessingThread::DebugProcessingThread()
{
...
myProcess = new QProcess(this);
myProcess->start("python abc.py");
connect(myProcess, SIGNAL(started()), this, SLOT(processStarted()));
connect(myProcess, SIGNAL(error(QProcess::ProcessError)), this, SLOT(processError()));
connect(myProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readStandardOutput()));
myProcess->waitForStarted();
}
void DebugProcessingThread::processError()
{
qDebug("PROCESS ERROR");
qDebug() << myProcess->errorString();
}
void DebugProcessingThread::readStandardOutput()
{
qDebug("READ DATA");
qDebug(myProcess->readAll().toStdString().c_str());
myProcess->write("out.txt\n");
}
void DebugProcessingThread::processStarted()
{
qDebug("Process has started");
}
The above code works perfectly.
But I want to send and receive data from function:
void DebugProcessingThread::run()
{
myProcess->write("out.txt\n");
// This Throws socket Error
}
Keep long story short, you shouldn't instantiate anything you going to use in your new thread in the constructor, as every object instantiated there will get an affinity of the thread where your QThread object is created, common practice is either not to subclass QThread at all, just use QObject and moveToThread, and then connect some slot like init() to QThread started() signal, so you can do all initialisation inside the init() which will run inside a new thread, or if for whatever reasons you need QThread subclassing instantiate everything in run().
Also pay attention that QThread itself is nothing more nothing less then a wrapper of your real thread and stays as an object in a thread where you created it.
Consider the following in Qt using QtSoap lib:
QtSoapHttpTransport http;
http.setHost("XXXX",3333);
connect(&http, SIGNAL(responseReady()), this, SLOT(getResponse()));
now there is a method i want to call which is:
QtSoapMessage request;
request.setMethod("test");
request.addMethodArgument("xxx","zzzz",xxx);
request.addMethodArgument("xx","xx",xx);
http.submitRequest(Request, "/api/soap");
now i want to have something like this :
QString GetTest(){
while(http.isBusy); // no such a thing as isbusy
return http.getResponse().returnValue().toString();}
or any technique i can use to get the return value or wait for it and get it..
Thanks in advance...
I don't see a problem. The QtSoapHttpTransport reference already has a nice simple example.
If you want to have a getter that blocks and returns only when the response is received, doing active wait (your while loop) is absolutely not a way to go.
You already connect the responseReady signal to your slot, so the only missing thing would be to have a synchronization point that blocks your thread calling getTest until this slot is executed.
class Messenger : public QObject {
Q_OBJECT
public:
Messenger() { /* ... your initialization code with connect ... */ }
void sendRequest() { /* ... your sending code ... */ }
QString getTest() // call this from a worker thread to wait
{ // for a response to arrive and retrieve it
QMutexLocker lock(&responseMutex);
responseReady.wait(&responseMutex);
return http.getResponse().returnValue().toString();
}
public slots:
void getResponse() { // slot called by Qt event loop when response arrives
responseReady.wakeAll();
}
private:
QtSoapHttpTransport http;
QWaitCondition responseReady;
QMutex responseMutex;
};
Note that this design only makes sense if you have a multithreaded application and the thread calling getTest is a working thread, not event-driven thread.
On the other hand, if your application just wants to do something with the received response, there is imho no reason why you need a blocking method in the first place. Just perform your actions in the slot directly - just like it is in the Qt documentation.