I have done something like this:
//in the mainwindow's constructor
QThread *thr = new QThread;
soundWorker * work = new soundWorker;
connect(this,SIGNAL(playsound()),work,SLOT(process()));
work->moveToThread(thr);
thr->start();
Shall I delete thr and work at the deconstructor of mainwindow?
You can use the default Qt way of managing memory by assigning a parent to the QThread, i.e. do this:
QThread *thr = new QThread(this);//the mainwindow's is now the thread parent
In Qt, parents are responsible for managing the memory of their children. Thus, the QThread will be automatically deleted when needed.
Then, for your soundWorker, you have a few different solutions. If its lifetime is the same as your mainwindow, as you hint when you ask if you should delete it in the destructor of the mainwindow, you could simply make it a non-pointer member, and its storage duration would then become automatically handled.
The parent thing is specific to Qt though. In general, when you deal with memory yourself, you should resort to wrappers (such as smart pointers) that enables RAII.
Further reading: Qt Trees and ownership model
You can use the QThread::finished() signal in order detect the moment you wish to release the QThread pointer. Same thing could be done with QObject pointers which were moved to the new thread.
Considering that the moment of closing the main window is the moment of closing the whole application and considering that you don't need to further do processing after the application was closed, you can pass the main window pointer as a parent to the QThread by either passing it to the constructor or using QObject::setParent.
Releasing the resources acquired inside the thread handled by QThread must be handled separately as you can't make the QThread object a parent of a resource managed by it - QThread lives in the thread where it was created and not in the thread it manages.
More details here.
Related
I'm using threaded application written in Qt (C++).
I need to make get/post request very often from separate threads.
Qt doc says:
One QNetworkAccessManager instance should be enough for the whole Qt
application. Since QNetworkAccessManager is based on QObject, it can
only be used from the thread it belongs to.
Is static thread_local QNetworkAccessManager good choice for my purpose?
No, not a good choice.
You shouldn't create static or global QObject subclass instances, because you generally need them to be created after the Qt application object has been created (a lot of Qt stuff depends on the application object existing already). C++ does not really provide very good control over when static objects are actually created, and here you want to have that control.
Just use a pointer and new to create the QNetworkAccessManager instance, as many of them as you want. You could create them in the right thread directly, or you could create them in some other (usually main) thread and move them to the right thread.
To get them destroyed properly, when they don't have a natural parent (because the parent must live in the same thread!), connect the their thread's QThread::finished signal to the objects QObject::deleteLater slot, and they will get cleanly deleted when the thread finishes.
If you want a plain function, which uses the current thread's QNAM instance, you could have thread-local static pointer. Something like
static thread_local *thread_qnam;
void myfunc() {
if (!thread_qnam) {
thread_qnam = new QNetworkAccessManager;
connect(QThread::currentThread, &QThread::finished(), thread_qnam, &QObject::deleteLater);
// Whatever other setup you need.
// It'd probably be good idea to wrap this in a function.
}
// Use thread_qnam...
}
I would like to know what difference there is between new QThread(this) and new QThread() and how this would influence the behaviour of my code when using QThread.
The parent of a QThread does not make any difference on who executes what.
It is just the classic parent-child relationship in Qt, the Object-Tree, meaning the parent takes ownership of the QThread instance and will delete its child when it gets deleted.
What is important when it comes to threads in Qt is
Where do you create a QObject instance (by default the object belongs to the thread that created it)
The parent of a QObject instance (when you do a QObject::moveToThread(QThread *targetThread) all the children of the object are moved too)
Because : the slots of a QObject are executed in the thread that it belongs to.
I have a question concerning the Slot-/Signal-architecture in Qt. For my project I have separate functions for:
a) GUI
b) controlling external devices
Now I want to have function b) constantly listening to Signals sent from a) on specific slots. But this listening should not influence the GUI thread, e.g. I want to continue with my work there.
Thus I had the idea to move the function b) to a separate thread. But my problem is that I do not know how to create the run-function in this thread. It should start with my program (no problem), and it should constantly listen to incoming signals and then run the function which is connected to this signal.
Would a simple while(1) be enough?
Qt makes this pretty straightforward. I would not advise overriding run() for this as it is not necessary - also it is not as flexible or easy to implement, and has a few caveats regarding object creation.
Instead, just create a thread then move your listening object to it. For example:
// 'this' as parent means thread will terminate automatically when 'this'
// is deleted, you have other options here, of course.
QThread *thread = new QThread(this);
// Create your object (or just use an existing one). Note new object initially
// lives on current thread. Note also it does not have a parent. Objects with
// parents cannot be moved to other threads explicitly.
MyObject *object = new MyObject(); // Assuming MyObject is a QObject.
// Now move the object to the new thread.
object->moveToThread(thread);
// And, you'll want to make sure the object is deleted when the thread ends.
connect(thread, SIGNAL(finished()), object, SLOT(deleteLater()));
connect(thread, SIGNAL(terminated()), object, SLOT(deleteLater())); // just in case
// Finally, start the thread:
thread->start();
That's all you need to do! Now the thread is running, with its own event loop, and signals connected to the object's slots will be queued and run on that thread†.
Note that if your object's constructor creates any QObjects of its own, it should set itself as those objects' parent accordingly. Qt will automatically move all child objects of your object to the thread as well when you do object->moveToThread().
You can move as many objects as you want to a given QThread, it isn't limited to just one.
To explicitly end the thread, and clean up the object, call thread->exit() or just delete the thread. Again, though, since we made this a parent of the QThread in the above example, you really don't need to do any cleanup at all.
By the way, if you have some initialization or other tasks that your object should perform on the thread when the thread is started, you can also use the thread's started() signal:
connect(thread, SIGNAL(started()), object, SLOT(initializeWhatever()));
Note, of course, that any objects used in the above way must be subclasses of QObject. This is where e.g. moveToThread() and deleteLater() are, and is also required for proper handling of slots:
class MyObject : public QObject {
Q_OBJECT
public:
MyObject (QObject *parent = 0);
signals:
...
public slots:
...
};
The easiest way, really, to set this up is in QtCreator, right click, add a new class, and choose QObject as a base there. Qt will set up a template header and source file for you.
† Unless the connection type is DirectConnection, but by default it is not.
The last weeks I read a lot about RAII and thought that I should start using smart pointers in my applications. As an example I tried to modify one of my applications. It captures frames from a webcam in a thread, performes image processing in another thread and displays the processed and unprocessed images in QT widgets. One central Object is the CCameraHandler which controls the capturing thread and image processing thread. Up to this point I used 4 plain pointers as members in this class:
CCameraCapture* m_CameraCapture;
CImageProcessor* m_ImageProcessor;
QThread* m_CameraCaptureThread;
QThread* m_ProcessingThread;
In the constructor of CCameraHandler I created the Instances using new and moved the capture object to the thread:
m_CameraCaptureThread= new QThread();
m_CameraCapture= new CCameraCapture();
//Move camera capture object to thread
m_CameraCapture->moveToThread(m_CameraCaptureThread);
That approach worked nicely. Now I wanted to a first test with QScopedPointer and tried to change m_CameraCapture to a QScopedPointer using
QScopedPointer<CCameraCapture> m_CameraCapture;
and initializing it with CameraCapture(new CCameraCapture()) in the initialization list. It compiled nicely and works as it should but when I close the application an the destructors are called I get an error from Qt:"Cannot send events to objects owned by a different thread. Current thread 5ff590. Receiver '' (of type 'CCameraCapture') was created in thread 4b7780" I guess that it has to do with the m_CameraCapture->moveToThread(m_CameraCaptureThread); where I now move a scoped pointer. Is the QScopedPointer automatically parented by CCameraCapture? So far I used
//This connections guarantees that the m_CCameraCapture and m_CameraCapture are deleted after calling QThread::exit()
QObject::connect(m_CameraCaptureThread, SIGNAL(finished()), m_CameraCaptureThread, SLOT(deleteLater()));
QObject::connect(m_CameraCaptureThread, SIGNAL(finished()), m_CameraCapture, SLOT(deleteLater()));
to delete thread an worker when camera capturing is stopped. If m_CameraCapture is now parented by CCameraHandler that might cause the problems. At the moment I am not so sure if it is a good Idea to use a SmartPointer in this case. Any Ideas what might cause this error on destruction?
Edit:
The CCameraHandler dtor looks like this (threads should be deleted before the worker):
CCameraHandler::~CCameraHandler(void)
{
//Stop grabbing and processing
emit stopGrabbing();
emit stopProcessing();
/*Wait for the capture thread to terminate. The destructor of CCamera Handler might be called on application close. Therefore it is important to wait for QThreads to terminate. Else the application might close before threads get deleted*/
m_CameraCaptureThread->exit();
m_CameraCaptureThread->wait();
//Wait for the processing thread to terminate
m_ProcessingThread->exit();
m_CameraCaptureThread->wait();
qDebug() << "CCameraHandler deleted";
}
An object that has been moved to another thread must be destructed either:
From the thread itself, or
From any thread after the thread itself has been destructed.
Caveat: QThread is not safe to be destructed before you stop it. To do that safely to a thread that merely runs an event loop, you should use the following subclass instead:
class Thread : public QThread {
using QThread::run; // final
public:
Thread(QObject * parent = 0) : QThread(parent) {}
~Thread() { quit(); wait(); }
};
Given such a class, destructed from the GUI thread, you simply need to destruct it before you destruct any objects that were moved to the thread. Of course, it's not necessary to hold such objects as pointers at all, but the code below will work whether you hold them directly or as pointers.
class Foo : public Bar {
CCameraCapture m_CameraCapture;
CImageProcessor m_ImageProcessor;
Thread m_CameraCaptureThread;
Thread m_ProcessingThread;
...
}
When the class is destructed, the following happens, in order:
~Foo() body runs (it may be empty).
Members in the ... section, if any, are destructed in reverse order of declaration.
m_ProcessingThread.~Thread runs, followed by superclass destructors (~QThread, and finally ~QObject). Any objects that were moved to that thread are now threadless.
m_CameraCaptureThread.~Thread runs, followed by superclass destructors. Any objects that were moved to that thread are now threadless.
m_ImageProcessor destructors run. As a threadless object, the destruction is safe from any thread.
m_CameraCapture destructors run. As a threadless object, the destruction is safe from any thread.
If you used QScopedPointer<...> to hold those instances, things would be exactly the same, just that every object's destruction would be wrapped in the body of ~QScopedPointer<...>.
Note that the use of even a raw pointer to hold those instances is a premature pessimization: you waste a bit of heap, and access to the instances is a bit slower due to an extra layer of indirection. Those things in isolation may not play a big role, but if there are thousands of objects all coded that way, things can add up.
Don't allocate class members in individual heap blocks unless absolutely necessary.
Problem is that you are doing some UI stuff from none UI thread.
It is hard to tell exactly where is the problem since you didn't give information what exacly CCameraCapture do.
I suspect that after capturing a frame you are setting a pixmap on label (to show frame) instead emit a signal with new frame and connect this signal with respective slot of UI element. So I think that scoped pointer and signal and slots have nothing to do with your problem, problem is that you didn't use signal slot mechanism in place where it was required.
What are the lifetimes of Qt Objects?
Such as:
QTcpSocket *socket=new QTcpSocket();
When socket will be destroyed? Should I use
delete socket;
Is there any difference with:
QTcpSocket socket;
I couldn't find deep infromation about this, any comment or link is welcomed.
Qt uses parent-child relationships to manage memory. If you provide the QTcpSocket object with a parent when you create it, the parent will take care of cleaning it up. The parent can be, for example, the GUI window that uses the socket. Once the window dies (i.e. is closed) the socket dies.
You can do without the parent but then indeed you have to delete the object manually.
Personally I recommend sticking to idiomatic Qt and using linking all objects into parent-child trees.
Objects allocated with new must be released with delete.
However, with Qt, most objects can have a parent, which you specify as an argument to the constructor. When the parent is deleted, the child objects get deleted automatically.
If you don't want to pass a parent for some reason (because there is no QObject where it makes sense to own the socket object), you can also use a QSharedPointer to manage the lifetime.