have spent a decade building and debugging threading frameworks in Java and .NET, it’s increasingly starting to look like threading is a bad idea; don’t go there” -- Leading Sun developer Tim Bray
all the time. • Useful for I/O intensive apps - no need to deal with threads. • Main theme: "Let me know when this operation is done". • Async Programming is not Threads - but it can turn out very useful. We'll talk about that on the Networking Module
threads a-la Java • (almost) No synchronization or locking is required • Best for sending tasks to secondary threads and not worry about it. • Starts to be a pain when we need to monitor progress
derived from QRunnable • QThreadPool is used to start a task in its own thread • We can poll the ThreadPool for status, but in general we use custom progress events • Just like Java • Remember to include <QtCore>
QCoreApplication a(argc, argv); for ( int i=0; i < NUM_THREADS; ++i ) { CountTask *c = new CountTask( QString("task[%1]").arg(i), 0, 100, 1); // QThreadPool takes ownership and // will delete c at the end QThreadPool::globalInstance()->start(c); } return a.exec(); }
• This call will run a slot from another object by its name • It uses the same mechanism as emitting a signal, but does not require a QObject • Let's See how it works !
QThreadPool • To enter the pool, we must have a QRunnable at hand • Thread communication is done using shared variables • Use a volatile bool as a kill switch • Use QMetaObject::invoke to mark progress • Consider using Signals/Slots when data needs to be passed around between threads
process multiple values in a Map/Reduce Style. • Best use when a lot of work is needed, but you wish Qt will take care of splitting it to threads. • Works best when the work can be modeled as a collection of items in a sequence.
Map: Take a list and return a list of the same size ◦ Filter: Take a list and return a (probably) smaller list ◦ Reduce the resulting elements to a single one
◦ There are many items to work on ◦ It's easy to tell what needs to be done ◦ It's tedious to split the work yourself • Map returns a list of the results • Filter returns a list of the originals that match a criteria • Reduce works on the matches to return a single value
an OS independent way • Represents a separate thread of control within the program. • A QThread start() method will create a new thread, start the run() method, and finish the thread when the run() ends • QThread works best for start-and-report background tasks
start a new thread by calling start() • The start() method returns immediately, and normal code execution continues. • Some time in the future the run() method is invoked from the new thread • default run() implementation starts an event loop
specific thread's event loop. All its slots are called in the context of its thread. • Use QObject::moveToThread to change an object's thread affinity (which means its event loop). • If a QObject has a parent, It is not possible to change its thread affinity. • Qt uses a Message Queue to pass signals between threads.
• Methods: ◦ lock ◦ tryLock ◦ unlock • If the mutex is already locked, any other thread trying to lock it will sleep until it is unlocked • When the mutex is unlocked, a single thread that is blocked on lock will be released and start its work
thread to tell another thread that a condition has been met, and it is now safe to resume work • Perfect for Producer/Consumer • Methods: ◦ wait ◦ wakeAll() ◦ wakeOne()
always be created in the thread where the parent was created. This implies, among other things, that you should never pass the QThread object (this) as the parent of an object created in the thread (since the QThread object itself was created in another thread). •
used in a single thread. Specifically, this applies to the timer mechanism and the network module. For example, you cannot start a timer or connect a socket in a thread that is not the object's thread.
created in a thread are deleted before you delete the QThread. This can be done easily by creating the objects on the stack in your run() implementation. • all threads must be cleaned up using wait() before the program ends.
connection, you are allowed to choose the connection type. Here are the available types: ◦ Auto (default): If the signal was made from the same thread, this is the same as direct. If it's from another thread, this is the same as queued ◦ Direct: The slot is invoked immediately in the sender's thread ◦ Queued: The slot is invoked when control is returned to the Event loop of the receiver thread, within the context of the receiver.
to be put in another thread. During the course of processing, status information should be sent to the GUI thread. Solution Use a QThread derived class and emit the relevant signals
it perform different tasks upon request. This means communication to and from the worker thread is required. Solution Write a QObject derived class and have it implement the required signals and slots. Move it to another thread's event loop.