Question about QThread implementation - multithreading

A QThread object represents a single thread of execution. But is the OS thread created when the QThread object is created, or when the start() method is called?
I'm interested in whether I can have several QThread objects lying around, and the OS will create threads on start() and kill them after run() returns, and then I can reuse the QThread objects again. But I don't want to hold OS resources while the QThread objects are not doing anything.
(for the record, I'm aware of QtConcurrent and the QThreadPool, and no, they don't satisfy my needs in this situation)

In Linux the thread object is created (via pthread_create) during the QThread::start method. It looks about the same with Windows.
You can see the source here:
Unix: http://qt.gitorious.org/qt/qt/blobs/master/src/corelib/thread/qthread_unix.cpp (line 542).
Windows: http://qt.gitorious.org/qt/qt/blobs/master/src/corelib/thread/qthread_win.cpp (line 419).

Related

Global variable declaration in Qt

I have made a Gui thread and a QTcpSocket thread in Qt.I want to access data
from QTcpSocket thread to Gui thread.How to solve it?
Do i need to declare some global variable and how?
The easiest way is to communicate via signal-slot connections. There is one QObject in each thread. The sending object has a signal, which is connected to the slot of the receiving object in the other thread.
In this setup, you make sure that the objects on both ends of the connections are configured to live in the correct threads. You might need to call QObject::moveToThread(). QObject also has a property where you can get the current thread (for debugging purposes in this case).
Then just establish the signal-slot connection as usual. Since both objects are in different threads, when the signal is triggered, a slot invocation event will be placed in the event loop of the receiving flag. This is explained in the Qt documentation, look for Qt::QueuedConnection.
The QTcpSocket is created from the gui thread.
So at that point the gui thread has a pointer to the socket object.
It then creates a connection between a slot in the gui and a signal in the socket.
In the socket object whenever you get data you simply emit a signal containing the data, which will be picked up by the gui thread.
You can pass any Qt type eg QString, QByteArray (or a raw pointer), through a signal/slot very efficiently. The details if signals between threads are also handled automatically.

Qt - Worker thread freezes the UI

This is my first experience on threading with Qt, so bear with me.
I have a singleton "system" object which periodically executes a heavy piece of code.
I control the system singleton from my UI, but the system is not aware of the UI.
I create a thread in my main, and then move the system to it:
QThread systemThread;
System::instance()->moveToThread(&systemThread);
systemThread.start();
qApp.exec();
The UI hangs until the system's periodical processing cycle is complete.
I have also tried to subclass QThread and calling exec from the run method.
What could be the problem? I'm certainly doing something wrong.
Best regards
See the excellent article about Threads, Events and QObjects in the Qt developer wiki. Something seems to be wrong with the thread affinity, you can check that with QObject::thread().
I advice you to follow this guideline from a Qt Developer himself when implementing multithreading: https://www.qt.io/blog/2010/06/17/youre-doing-it-wrong
It is way more effective and painless.
systemThread.start() will start systemThread.run() method in thread so you need to implement it inside run().
To create your own threads, subclass QThread and reimplement run().

Threads, QRunnable and QThreadPool, I can't fit in the details

I know the general theory, Thread, QRunnable and QThreadPool. How does it all fit in ? I mean when an instance of QRunnable is created, and assigned to the ThreadPool, what does it mean to start a thread ? Can multiple threads access the same QRunnable ? Does one QRunnable necessarily map one-to-one with one worker thread ?
QRunnable encapsulates a task that you want performed in a separate thread. If you need to know which thread is running that task or share it between threads, then you are probably doing something more complicated than what QThreadPool is designed to empower. In that case, you would create custom behavior using QThread directly. "Starting" a QRunnable with a QThreadPool is analogous to queueing that task for an available thread in the pool. Whereas, starting a QThread actually allocates a new OS thread and executes it.
The thread pool will manage a finite number of threads with a work queue of QRunnable instances. As a thread becomes available, it will be assigned a QRunnable to process. You don't need to explicitly create any QThread instances if you are using QThreadPool with QRunnable. Note that you still must ensure that shared resources are synchronized (e.g. with a QMutex, QMutexLocker, QReadWriteLock, QSemaphore, and/or QWaitCondition) when used in QRunnable instances.

Modifying QStandardItemModel from non-UI QThread?

I have Qt4 app which binds QStandardItemModel to the QListView and have the model updated from background/non-UI thread.
Sometimes, when the QStandardItem's setText(..) method is called very repeatedly from the non-UI thread, the application will crash at a la dataChanged(..) handler. I can reproduce the issue by calling setText("xxxxx") repeatedly in a for loop. In my app, the data is read from network hence I update the model in separate, non-UI thread.
Is this a common pb? If I understand correctly, this is related to queued connection and QStandardItemModel is not thread safe? How to get around this issue?
Thanks!
QStandardItemModel is part of the QtGui Library, iirc all classes in there are considered not threadsafe. You should be ok if you move the actual setting of the data into the GUI thread. You can do that pretty easily by using a queued signal from you network thread.

Why are slots being called from the main thread?

I have a Qt application that has two threads: the main thread that handles the GUI and a second thread that manages network connections. Here is the thread code:
void thread::run()
{
QTcpServer server;
server.connect(&server,SIGNAL(newConnection()),this,SLOT(OnConnect()));
//...
}
When I put a breakpoint at the start of OnConnect() and debug the application, it announces that OnConnect() is being called from the main thread!
How can I have OnConnect() run in the same thread as the QTcpServer?
To give a more thorough answer, look a little deeper into how signal-slot connections and thread contexts interact. Basically, for more connections (auto-connect), the slot will be directly called if both the emitter and the receiver are in the same thread context, otherwise it will be a queued connection, and the slot will be run in the thread context of the object that contains the slot. In this case, it must be queued, which implies that your thread is part of the main application's thread context, not its own. This is reinforced by the documentation Qt provides for an overview of its threading, where it states that the QThread instance is "owned" by the thread context that created it, not the thread context that it represents. This means you have three main choices:
You can use moveToThread() to move the thread into its own context. Note that this may cause problems when deleting the thread unless you move it back to the context where it will be destroyed, and this can only be done in the source-thread context, so it would have to be done before the run function exited.
You can treat the QThread instance as a handle to the thread, not as being part of the thread itself. If you need things done in the context of the new thread, create a different object to handle those, and instantiate them in the context of the new thread (inside the run function). This is what I would recommend.
Force a direct connection. This means you would need to ensure the code running in the slot is thread-safe, ignoring Qt's built-in methods of making those functions thread-safe. This is what you have done.
It seems like the problem was that I wasn't passing Qt::DirectConnection as the last parameter of connect().
After adding that, it worked.

Resources