Qt threading stopped UI from responding - multithreading

I think I might misunderstood several concepts in Qt's threading,
In my window class, which is derived from QWidget:
class Widget
{
Q_OBJECT
public:
Widget::Widget (QObject *parent = 0) : QObject(parent)
{
moveToThread(&th); // still stuck
connect (&th, SIGNAL(started()), SLOT(doWork()));
th.start();
}
private:
QThread th;
private slots:
void doWork ()
{
// hmm, this stuck the UI
while (1)
{
qDebug() << "Sleeping";
}
};
};
The forever loop stuck the UI, it shouldn't be, since that was called by the QThread.
Can anyone point out what's wrong about this code?

Widget::dowork() is executed on the main thread (on which the GUI runs), that's why it blocks. It doesn't matter that it was called by a QThread.
The correct way to execute code on another thread is to first move a QObject instance to a QThread using QObject::moveToThread(), and then connect the started() signal of the QThread to the slot of the QObject instance that you want executed.
If you want to know more: https://www.qt.io/blog/2010/06/17/youre-doing-it-wrong
Another issue with your code is that you're trying to move a QWidget-derived object to another thread. This is not allowed. QWidget instances must remain on the main thread. Instead, you should subclass from QObject.
Yet another issue with the code is that you're doing this in the constructor. Moving the object to another thread while it's not fully constructed yet is just asking for trouble.

Related

QSerialPort in QThread run bytesAvailable is zero

Have a simple Qt app. Gui thread, creates Dev thread it creates (in its run()) Read thread. Dev and Read threads are my classes inherited from QThread. The Read thread should read data from COM port continuously. An approximate view of Read run is following.
read::run()
{
sp2->clear();
while (DO_EXEC)
{
if (DO_WRITE)
{
// write data to port
}
usleep(500);
ba = sp2->bytesAvailable();
if (ba > 0)
{
int a = sp2->read(&BUF[BUF_END], ba);
// process data
emit sgnl(sendeddata);
}
}
}
To start it I emit signal in GUI that is passed to Dev at it is passed to the following read slot:
read::slot_readStart()
{
// some stuff
if (doStart && !isRunning())
{
sp2 = new QSerialPort(this);
sp2->setPortName("COM3");
sp2->setBaudRate(256000);
sp2->setDataBits(QSerialPort::Data8);
sp2->setStopBits(QSerialPort::OneStop);
sp2->setParity(QSerialPort::NoParity);
sp2->setFlowControl(QSerialPort::NoFlowControl);
sp2->setReadBufferSize(5000);
bool isOpen = sp2->open(QIODevice::ReadWrite);
DO_EXEC = true;
start();
}
}
This works. But, if I place creating and setup and opening serial port to run method, then the port is open, but the bytesAvailable() are always zero? Why it is possible?
Thank you in adcance.
I agree with Orest Hera, in that you are using a "non recommended" way of implementing threads.
You are using inheritance for your thread object.
It is important to understand how QThreads work. The general procedure to using the QThreads is:
Make Object to go into thread, assign no parent
Make thread
Move object into thead using obj->moveToThread(thread)
Connect a signal to a slot in the object that will instatiate the object members (if required)
Start the thread: thread->start()
For example:
MyObj *myObj = new MyObj(0); // 0 = no parent if your object inherits QObject
QThread* thread = new QThread;
myObj->moveToThread(thread);
QObject::connect(thread, SIGNAL(started()), myObj, SLOT(run()));
thread->start();
So your object can still have its "run()" function, but it won't be overloading anything.
Also your run() function does not need to be a "forever" loop, it is simply an initialization function (create the serial port or whatever). Then you add other slots for other events, e.g. you can connect the QSerialPort::readyRead() to your "incoming data slot" handler to handle any data received from the serial port.... and so on.
I think this will solve your issues. It is difficult to tell exactly why your serial port does not work in your overloaded "Run()" function because I can't see how you are calling /creating the thread (i.e. the rest of your code) or where DO_EXEC is initialized etc... There is probably some ordering of events or thread ownership issue here.
Note: I am not saying you can't inherit thread class, but if you do that it is so that you create your own custom thread class (to do thread stuff), but not some other class to create a hybrid of thread utility and other stuff. There is a fair amount of information relating to this here (on SO) and on the qt forum if you are interested in the why/how etc... :)

Update Scene from Thread?

I need to update a QGraphicsView with a QGraphicsScene from a thread.
Below is some pseudo'ish code example of what I am doing which is causing me issues (runtime errors).
What am I doing wrong, and how should I be doing it?
Main App:
void Main::startThread()
{
view = new QGraphicsView(...);
thread = new MyThread(...);
connect(thread, SIGNAL(doSceneUpdate(QGraphicsScene*)), this, SLOT(updateScene(QGraphicsScene*)));
thread->start();
}
void Main::updateScene(QGraphicsScene *scene)
{
view->SetScene(scene);
view->show();
repaint();
}
The Thread:
void MyThread::run()
{
QGraphicsScene *scene = new QGraphicsScene(...);
while(1)
{
//draw stuff on the scene
emit doSceneUpdate(scene);
//some delay
}
Thanks in advance!!!
[edit]
The error is:
ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread. Current thread
3e53c0. Receiver '' (of type 'QGraphicsScene') was created in thread 1476cd18", file c:\Qt\qt-everywhere-opensource-src-4.8.2\src\corelib\kernel\qcoreapplication.cpp, line 501
What am I doing wrong, and how should I be doing it?
I think the canonical answer is here -- in a nutshell, the article states that you shouldn't be subclassing QThread, but rather you should use a "bare" (i.e. not-subclassed) QThread object and connect its started() signal to a slot that will then be run in the context of that thread, after the thread starts. That way the object-thread-ownership issues are handled automatically for you.
Note also that threads other than the main Qt thread are generally not allowed to create or interact directly with GUI objects like QGraphicsScene, since doing that would introduce race conditions due to the operations going on simultaneously behind the scenes in Qt's GUI event loop. If you want to use a separate thread, you'll need to keep it away from your GUI objects, and instead just have it emit asynchronous signals and/or send Events to the main/GUI thread to get the main/GUI thread to do the GUI-object updates on its behalf.
The problem is with your connection line. You are connecting a slot to a signal which does not make sense. You should connect the signal from the thread to the slot :
connect(thread, SIGNAL(doSceneUpdate(QGraphicsScene*)),this, SLOT(updateScene(QGraphicsScene*)));
in
void MyThread::run()
{
QGraphicsScene *scene = new QGraphicsScene(...);
...
}
do you pass this to the constructor of QGraphicsScene()?
That could be one cause of error, since now you are passing a child of MyThread to Main
Try creating a QGraphicsScene object on the stack or with the parent as NULL ( new QGraphicsScene(0) )

How to run one function in another thread

I'm standing in front of a small (maybe not) problem. I have one function which parses XML file (very big xml ~1Gb) so it takes many time (5-6 mins to finish the func). I don't want to use it in GUI-thread because of known issues (mainwindow freezes and nothing happened, so user thinks everything goes wrong). I've tried to solve this problem by using
QtConcurrent::run
But one more problem appeared: if user press X (close button in top right corner) main GUI-thread goes down, but child-thread which was generated my QtConcurrent::run continue his work and I can kill him only by task manager.
I've decided to use QThread instead of QtConcurrent::run6 but I don't understand how can I run MainWindow class function:
void MainWindow::parseXML()
I've tried to create smth like this:
class pThread : public QThread
{
Q_OBJECT
private:
void run();
};
void pThread::run(){
MainWindow::parseXML();
}
But when I'm trying to compile it error appears:
cannot call member function 'void MainWindow::parseXML()' without object
Moreover, I don't know if it possible to update GUI-thread through this method (parseXML function changes statusBar)
What should I do?
The recommended ways to work with threads in Qt is not to inherit from QThread class, see the documentation here and you should be able to do it after that.
And yes it is possible to update the mainwindow from the thread, just code the signals and slots for that functionality, into mainwindow class code a slot that updates the progress and into the class that does the work (the xml parsing you need - there is no reason that functionality should be into the mainwindow class anyway) you code the signal that emit the progress and connect it with mainwindow's slot with Qt::QueuedConnection (note that the default auto-connection will become queued if the objects are in separate threads).
Another option is to use start a QRunnable with QThreadPool. you may want to check documentation. Be ware to wait the spawned threads with QThreadPool::waitForDone().

QNetworkAccessManager crashes on delete

I have a class 'Downloader' derived from QObject that runs in a worker thread. When the thread is started, the downloader creates a QNetworkAccessManager object on the heap, and starts to request files. I keep track of how many files have been requested and received. Once I've gotten all of the files, I delete the QNetworkAccessManager object and exit the thread. My problem is that deleting the manager object causes a crash no matter when or where I do this. I've even tried manager->deleteLater(). If I don't delete it, my code runs great, but I know there is a memory leak there. Here is a stripped down version of my code.
Creating the downloader and thread, and setting signals up so that starting the thread starts the downloads, and when the downloads are complete, the thread stops:
QThread thread;
Downloader downloader;
downloader.setFiles(files);
downloader.moveToThread(&thread);
downloader.connect(&thread, SIGNAL(started()), SLOT(downloadFiles()));
thread.connect(&downloader, SIGNAL(downloadsFinished()), SLOT(quit()));
thread.start();
Implementation for the downloader:
void Downloader::downloadFiles()
{
QNetworkAccessManager *manager = new QNetworkAccessManager();
connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(finished(QNetworkReply*)));
receivedCount = 0;
requestCount = files.count();
for (QStringList::const_iterator pos = files.begin(); pos != files.end(); ++pos)
{
QUrl url(*pos);
manager->get(QNetworkRequest(url));
}
}
void Downloader::finished(QNetworkReply *reply)
{
// *** Get the file data and process it *** //
++receivedCount;
reply->deleteLater();
if (receivedCount == requestCount)
{
// manager->deleteLater();
emit downloadsFinished();
}
}
The commented out line will crash the app. Even deleting the manager in Downloader's destructor, or setting the downloader as the manager's parent will crash the app.
I first tried creating the manager as a regular member variable on the stack, but doing so causes errors of it's own since the manager would be created in the GUI thread and later try to create children on a different thread.
And before anybody says "QNetworkAccessManager is asynchronous. Why use it in a worker thread?" I have my reasons. It shouldn't be THAT unheard of to do something like this.
The only obvious problem is below but I am not sure if you have posted your entire code or not
void Downloader::downloadFiles()
{
QNetworkAccessManager *manager = new QNetworkAccessManager();
You are creating a local QNetworkAccessManager *manager in your method but not keeping a reference to it and then trying to access it within finished() method.
You should assign new QNetworkAccessManager(); a member variable !

qt How to put my function into a thread

I'm a QT newbie. I have a class extend from widget like:
class myclass: public Qwidget
{
Q_OBJECT
public:
void myfunction(int);
slots:
void myslot(int)
{
//Here I want to put myfunction into a thread
}
...
}
I don't know how to do it. Please help me.
Add a QThread member then in myslot move your object to the thread and run the function.
class myclass: public Qwidget
{
QThread thread;
public:
slots:
void myfunction(int); //changed to slot
void myslot(int)
{
//Here I want to put myfunction into a thread
moveToThread(&thread);
connect(&thread, SIGNAL(started()), this, SLOT(myfunction())); //cant have parameter sorry, when using connect
thread.start();
}
...
}
My answer is basically the same as from this post: Is it possible to implement polling with QThread without subclassing it?
Your question is very broad . Please find some alternatives that could be beneficial to you :
If you want to use signal/slot mechanism and execute your slot within a thread context you can use moveToThread method to move your object into a thread (or create it directly within the run method of QThread) and execute your slot within that thread's context. But Qt Docs says that
The object cannot be moved if it has a
parent.
Since your object is a widget, I assume that it will have a parent.
So it is unlikely that this method will be useful for you.
Another alternative is using QtConcurrent::run() This allows a method to be executed by another thread. However this way you can not use signal/slot mechanism. Since you declared your method as a slot. I assumed that you want to use this mechanism. If you don't care then this method will be useful for you.
Finally you can create a QThread subclass within your slot and execute whatever your like there.
This is all I could think of.
I hope this helps.

Resources