Qt slot argument is corrupted - c++

The original code is to big to be posted here. Basically, I'm doing this:
class MySuperClass
{
QThread thread;
MyClass myObject;
MySuperClass()
{
connect( this, &MySuperClass::onKill, &myObject, &MyClass::stop );
connect( &thread, &QThread::started, &myObject, &MyClass::loop );
connect(&myObject, &MyClass::finished, &thread, &QThread::quit );
myObject.moveToThread( &thread );
qRegisterMetaType<uint16_t>("uint32_t");
connect( this, &MySuperClass::changed, &myObject, &MyClass::onChange );
}
void do()
{
emit changed(0);
}
}
'onKill - stop' signal/slot have no parameters and work fine. No problem here.
Problem is 'changed - onChange' pair. They have one parameter of type uint32_t (which I have registered).
When I call method do of MySuperClass from the main thread the signal is emitted, the slot onChange is called but it's parameter is not 0!
It's some big number like 3043426304.
The funny part is: if I change connection type to DirectConnection - parameter is zero; if I change connection type to QueuedConnection - parameter is zero too! How can this be? Isn't AutoConnection either Queued or Direct?
I'm very puzzled by this. First of all: how stack allocated integer type parameter may be corrupted like that? I'd understand if it was something heap-allocated or used in multiple threads.
My second question is: how should I do this connection properly? Does the order of connect and moveToThread matter?

Question 1 is answered by Chris. For question 2 (I did not see that the first time around)...
This is how to setup an object running in a seperate thread:
// Create the myObject object in its own thread
QThread* myThread= new QThread(); // you can assign `this` as parent if you want...
MyObject* myObject= new MyObject(0); // Assign no parent here (for QObject)
QObject::connect(myThread, &QThread::started, myObject, &MyObject::run, Qt::QueuedConnection);
myObject->moveToThread(myThread);
myThread->start();
You mostly have it correct. I think you are missing the "myThread->start()" function to kick the thread off. In your object creation its important to know that any dynamic allocations will be created in the parent thread space since the constructor runs before you move it to the thread. So its best to instantiate any objects you need inside the run() slot.
Any interaction with object once you start the thread should be via slots/signals.
Once you start the thread, it will emit started and your run() slot will be called.
The order of connect and moveToThread does not matter so long as you do all this before you call myThread->start()
Note
This is good for starting up a thread. There are some rules that may help you terminating the thread cleanly as well... but that's probably going off-topic

Related

QLabel not updating image content [duplicate]

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

Invoke slot asynchronously without connecting to it using clear line of code

I have encountered quite freaky bug - QAction::trigger caused blocking dialog to appear, which caused my server which called trigger to go stuck (eg. not able to process socket signals until dialog was closed).
I figured out a workaround. I connect signal void triggerWorkaround() to slot QAction::trigger using Qt::QueuedConnection and I emit it:
QObject::connect(this, &HackClass::triggerWorkaround, targetAction_.data(), &QAction::trigger, Qt::QueuedConnection);
emit triggerWorkaround();
QObject::disconnect(this, nullptr, targetAction_.data(), nullptr);
But that's three lines of confusing code. Is there a non-confusing method to do this? I have found QMetaObject::invokeMethod, but frankly, that's 10 times more confusing than my current solution. Also, I don't want to ever use method name as string!
You can separate that into a function QueuedInvoke like this:
//overload for methods/slots
//the slot gets invoked in the thread where the QObject lives
template <typename Object, typename T>
void QueuedInvoke(Object* object, T (Object::* f)()){
QObject signalSource;
QObject::connect(&signalSource, &QObject::destroyed,
object, f, Qt::QueuedConnection);
}
//overload for functors
//the functor gets invoked in the thread where the contextObject lives
//or in the current thread if no contextObject is provided
template <typename Func>
void QueuedInvoke(Func&& f, QObject* contextObject = QAbstractEventDispatcher::instance()){
QObject signalSource;
QObject::connect(&signalSource, &QObject::destroyed,
contextObject, std::forward<Func>(f), Qt::QueuedConnection);
}
This will leverage the destroyed() signal emitted from the temporary QObject to post a queued event into the event loop. The slot/functor is actually invoked when the event loop processes that event.
So, Instead of the 3 lines you posted, You can use the above function like this:
QueuedInvoke(targetAction_.data(), &QAction::trigger);
My answer is based on this great answer about executing a functor in a given QThread. You can refer to it for more details.

How to properly terminate QThread in Qt?

Is this a correct way terminate the thread ...
if(m_ReviewImageThreadLoader !=NULL)
{
m_ReviewImageThreadLoader->quit();
m_ReviewImageThreadLoader->wait();
m_ReviewImageThreadLoader->terminate();
delete m_ReviewImageThreadLoader;
m_ReviewImageThreadLoader = NULL;
qDebug()<<"m_ReviewImageThreadLoader closed"<<endl;
}
... where m_ReviewImageThreadLoader is the thread object.
The answer to your question depends to a large extent on the nature of the work being done on your thread. If the usage is something like...
QThread *m_ReviewImageThreadLoader = new QThread;
MyObject *mo = new MyObject;
mo->moveToThread(m_ReviewImageThreadLoader);
m_ReviewImageThreadLoader->start();
then your code should be fine (although you really shouldn't need the call to terminate()).
If, on the other hand, m_ReviewImageThreadLoader is of a type derived from QThread and has explicitly overridden QThread::run then you'll need to supply more information before your question can be answered.
Have you tried your code? Does it appear to work?

Calling lambda/std::function in main UI thread from a background thread [duplicate]

This question already has answers here:
How to execute a functor or a lambda in a given thread in Qt, GCD-style?
(5 answers)
Closed 6 years ago.
Im my mainthread, I have a Qt window running, which is calling my background thread (network service) and is eventually expecting responses which should be reflected in the UI:
// runs in main (GUI) thread
void QTServer::onButtonClick(){
srv->request(msg,
[this]
(std::shared_ptr<message> msg){
this->ui.txtResponse->setText("received a response" + msg.data());
});
}
The network service is as follows:
std::function<void(std::shared_ptr<message>)> delegate_;
void NetworkService::request(message& msg,std::function<void(std::shared_ptr<message> msg)> fn)
{
// send the request to the socket and store the callback for later
// ...
this->delegate_ = fn;
}
void NetworkService::onResponseReceived(std::shared_ptr<message> responseMsg)
{
// is called from the background thread (service)
// Here I would like to call the lambda function that the service stored somewhere (currently as an std::func member)
// psuedo: call In Main Thread: delegate_(responseMsg);
}
How does that work? Does it even work?
I know that you can use QMetaObject::invokeMethod(this, "method", Qt::QueuedConnection to call a function in the mainthread, so I tried the following:
void NetworkService::onResponseReceived(std::shared_ptr<message> responseMsg)
{
QMetaObject::invokeMethod(this, "runInMainThread", Qt::QueuedConnection, QGenericArgument(), Q_ARG(std::function<void(std::shared_ptr<message>)>, delegate_));
}
How do I pass the responseMsg here as an argument for _delegate?
void QTServer::runInMainThread(std::function<void(std::shared_ptr<message>)> f) {
f();
}
How to get rid of "No function with these arguments" error?
remove QGenericArgument() - it's internal helper class.
also you have to register your own types in order to use Q_ARG or send data as void* then cast it back.
Q_ARG(void*, delegate_)
2nd question - f is function which takes one argument - std::shared_ptr, and f() - call without argument, so add default argument
I believe the recommended way for what you are trying to achieve in QT is by using signals and slots in combination with QThread. For example:
MyObject * myObject = new MyObject(); //your worker
QThread * myThread = new QThread(); //your thread
myObject->moveToThread(myThread);
QObject::connect(myThread, SIGNAL(started()), myObject, SLOT(startWorking())); //when thread starts, invoke the working method
QObject::connect(myObject, SIGNAL(stoppedWorking()), this, SLOT(stoppedWorking())); //when worker signals it finished, invoke slot in main
QObject::connect(myObject, SIGNAL(stoppedWorking()), myThread, SLOT(quit())); //quit the thread when worker signals that it finished
QObject::connect(myObject, SIGNAL(gproxyExiting()), gproxy, SLOT(deleteLater())); //cleanup
QObject::connect(myThread, SIGNAL(finished()), myThread, SLOT(deleteLater())); //cleanup
This way the whole lifecycle is managed automatically for you and you can define whatever signals inside the worker and slots on the main thread to communicate with each other.

QObject: findChildren and QThread

I have a (somewhat) simple program that creates new threads, one per connection to a socket:
void TelnetServer::incomingConnection(qintptr socketDescriptor)
{
TelnetConnection *thread = new TelnetConnection(socketDescriptor);
connect(thread, SIGNAL(shutdownRequested()), m_controller, SLOT(shutdown()));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
}
after a new thread is created, I output to qDebug a list of all children of the parent that created the QThreads (TelnetConnection) like this:
QList<QObject*> activeTelnetConnections = m_telnetserver->findChildren <QObject *> (); // Find all QThreads that children of telnetserver
qDebug() << "Children: " << activeTelnetConnections;
Since my QThreads decend from Qobject, I expect to see a list of QThreads and more. However, I can't find the Qthreads! This is all I see:
Children: (QNativeSocketEngine(0x7eb880) , QSocketNotifier(0x7ea5f0) )
Why do I not see the child threads? Does this mean the threads are not associated with the parent object anymore? Or am I doing something wrong here...
Does this mean the threads are not associated with the parent object anymore?
It may have never been associated. When you construct the thread, you need to pass the parent to it, however your TelnetConnection seems to be wrong as it does not expect a parent argument, or you do not pass that which internally passes that further to the base class with the following constructor.
QThread(QObject * parent = 0)
or you have to call setParent() on it later.
void QObject::setParent(QObject * parent)
This would mean thread.setParent(this); for your code, but I would rather suggest to fix either your thread class constructor or the invocation of it.
Alternatively, you can also set the child for the TelnetConnection explicit, but I would suggest the proper construction if possible.