A cross head features two full-length slots that cross, which allows a flat-head screwdriver to be used and makes the screw usable even if one slot has been worn away. Another type that has two short slots that cross but does not have a small circular shape at the center is known as a Prince, Frearson or Reed head.
- Support for Signals and Slots¶ One of the key features of Qt is its use of signals and slots to communicate between objects. Their use encourages the development of reusable components. A signal is emitted when something of potential interest happens. A slot is a Python callable.
- I just got a Galaxy S5 and I keep hearing a loud beep during phone calls. It is not the minute minder that's going off because I've already checked that. I don't mind getting text message notifications or getting a notification that I have another call.
- Yet another implementation of a lock-free circular array queue. Faustino Frechilla. Rate this: 4.97 (68 votes). The calling thread will get blocked if another thread owns the lock that protects the queue. Because another thread already reserved a slot in the queue (writeIndex is not equal to readIndex).
- It is absolutely essential that you only make modifications to your Windows Forms controls from the message queue thread. A brief example. A simple example of using this is to create a new form, add a textbox and a button to it. Call the textbox myTextbox. At the top of the code file add another using statement for the threading library.
- CallContext is a specialized collection object similar to a Thread Local Storage for method calls and provides data slots that are unique to each logical thread of execution. The slots are not shared across call contexts on other logical threads.
Home > Articles > Programming > C/C++
␡- Communicating with the Main Thread
< BackPage 3 of 4Next >
This chapter is from the book C++ GUI Programming with Qt4, 2nd Edition
This chapter is from the book
This chapter is from the book
Communicating with the Main Thread
When a Qt application starts, only one thread is running—the main thread. This is the only thread that is allowed to create the QApplication or QCoreApplication object and call exec() on it. After the call to exec(), this thread is either waiting for an event or processing an event.
The main thread can start new threads by creating objects of a QThread subclass, as we did in the previous section. If these new threads need to communicate among themselves, they can use shared variables together with mutexes, read-write locks, semaphores, or wait conditions. But none of these techniques can be used to communicate with the main thread, since they would lock the event loop and freeze the user interface.
The solution for communicating from a secondary thread to the main thread is to use signal–slot connections across threads. Normally, the signals and slots mechanism operates synchronously, meaning that the slots connected to a signal are invoked immediately when the signal is emitted, using a direct function call.
However, when we connect objects that 'live' in different threads, the mechanism becomes asynchronous. (This behavior can be changed through an optional fifth parameter to QObject::connect().) Behind the scenes, these connections are implemented by posting an event. The slot is then called by the event loop of the thread in which the receiver object exists. By default, a QObject exists in the thread in which it was created; this can be changed at any time by calling QObject::moveToThread().
To illustrate how signal–slot connections across threads work, we will review the code of the Image Pro application, a basic image processing application that allows the user to rotate, resize, and change the color depth of an image. The application (shown in Figure 14.3), uses one secondary thread to perform operations on images without locking the event loop. This makes a significant difference when processing very large images. The secondary thread has a list of tasks, or 'transactions', to accomplish and sends events to the main window to report progress.
Figure 14.3 The Image Pro application
The interesting part of the ImageWindow constructor is the two signal–slot connections. Both of them involve signals emitted by the TransactionThread object, which we will cover in a moment.
The flipHorizontally() slot creates a 'flip' transaction and registers it using the private function addTransaction(). The flipVertically(), resizeImage(), convertTo32Bit(), convertTo8Bit(), and convertTo1Bit() functions are similar.
The addTransaction() function adds a transaction to the secondary thread's transaction queue and disables the Open, Save, and Save As actions while transactions are being processed.
The allTransactionsDone() slot is called when the TransactionThread's transaction queue becomes empty.
Now, let's turn to the TransactionThread class. Like most QThread subclasses, it is somewhat tricky to implement, because the run() function executes in its own thread, whereas the other functions (including the constructor and the destructor) are called from the main thread. The class definition follows:
The TransactionThread class maintains a queue of transactions to process and executes them one after the other in the background. In the private section, we declare four member variables:
- currentImage holds the image onto which the transactions are applied.
- transactions is the queue of pending transactions.
- transactionAdded is a wait condition that is used to wake up the thread when a new transaction has been added to the queue.
- mutex is used to protect the currentImage and transactions member variables against concurrent access.
Here is the class's constructor:
In the constructor, we simply call QThread::start() to launch the thread that will execute the transactions.
In the destructor, we empty the transaction queue and add a special EndTransaction marker to the queue. Then we wake up the thread and wait for it to finish using QThread::wait(), before the base class's destructor is implicitly invoked. Failing to call wait() would most probably result in a crash when the thread tries to access the class's member variables.
The QMutexLocker's destructor unlocks the mutex at the end of the inner block, just before the wait() call. It is important to unlock the mutex before calling wait(); otherwise, the program could end up in a deadlock situation, where the secondary thread waits forever for the mutex to be unlocked, and the main thread holds the mutex and waits for the secondary thread to finish before proceeding.
The addTransaction() function adds a transaction to the transaction queue and wakes up the transaction thread if it isn't already running. All accesses to the transactions member variable are protected by a mutex, because the main thread might modify them through addTransaction() at the same time as the secondary thread is iterating over transactions.
The setImage() and image() functions allow the main thread to set the image on which the transactions should be performed, and to retrieve the resulting image once all the transactions are done.
The run() function goes through the transaction queue and executes each transaction in turn by calling apply() on them, until it reaches the EndTransaction marker. If the transaction queue is empty, the thread waits on the 'transaction added' condition.
Just before we execute a transaction, we emit the transactionStarted() signal with a message to display in the application's status bar. When all the transactions have finished processing, we emit the allTransactionsDone() signal.
The Transaction class is an abstract base class for operations that the user can perform on an image. The virtual destructor is necessary because we need to delete instances of Transaction subclasses through a Transaction pointer. Transaction has three concrete subclasses: FlipTransaction, ResizeTransaction, and ConvertDepthTransaction. We will only review FlipTransaction; the other two classes are similar.
The FlipTransaction constructor takes one parameter that specifies the orientation of the flip (horizontal or vertical).
The apply() function calls QImage::mirrored() on the QImage it receives as a parameter and returns the resulting QImage.
The message() function returns the message to display in the status bar while the operation is in progress. This function is called in TransactionThread::run() when emitting the transactionStarted() signal.
The Image Pro application shows how Qt's signals and slots mechanism makes it easy to communicate with the main thread from a secondary thread. Implementing the secondary thread is trickier, because we must protect our member variables using a mutex, and we must put the thread to sleep and wake it up appropriately using a wait condition. The two-part Qt Quarterly article series 'Monitors and Wait Conditions in Qt', available online at http://doc.trolltech.com/qq/qq21-monitors.html and http://doc.trolltech.com/qq/qq22-monitors2.html, presents some more ideas on how to develop and test QThread subclasses that use mutexes and wait conditions for synchronization.
Related Resources
- Book $31.99
- Book $35.99
- Book $43.99
The QTimer class provides repetitive and single-shot timers. More..
Properties
- active : const bool
- interval : int
- singleShot : bool
- 1 property inherited from QObject
Public Functions
QTimer(QObject * parent = 0) | |
~QTimer() | |
int | interval() const |
bool | isActive() const |
bool | isSingleShot() const |
void | setInterval(int msec) |
void | setSingleShot(bool singleShot) |
int | timerId() const |
- 29 public functions inherited from QObject
Public Slots
- 1 public slot inherited from QObject
Signals
void | timeout() |
- 1 signal inherited from QObject
Static Public Members
void | singleShot(int msec, QObject * receiver, const char * member) |
- 7 static public members inherited from QObject
Reimplemented Protected Functions
- 8 protected functions inherited from QObject
Detailed Description
The QTimer class provides repetitive and single-shot timers.
The QTimer class provides a high-level programming interface for timers. To use it, create a QTimer, connect its timeout() signal to the appropriate slots, and call start(). From then on it will emit the timeout() signal at constant intervals.
Example for a one second (1000 millisecond) timer (from the Analog Clock example):
Qt Call Slot From Different Thread
From then on, the
update()
slot is called every second.You can set a timer to time out only once by calling setSingleShot(true). You can also use the static QTimer::singleShot() function to call a slot after a specified interval:
In multithreaded applications, you can use QTimer in any thread that has an event loop. To start an event loop from a non-GUI thread, use QThread::exec(). Qt uses the timer's thread affinity to determine which thread will emit the timeout() signal. Because of this, you must start and stop the timer in its thread; it is not possible to start a timer from another thread.
As a special case, a QTimer with a timeout of 0 will time out as soon as all the events in the window system's event queue have been processed. This can be used to do heavy work while providing a snappy user interface:
processOneThing()
will from then on be called repeatedly. It should be written in such a way that it always returns quickly (typically after processing one data item) so that Qt can deliver events to widgets and stop the timer as soon as it has done all its work. This is the traditional way of implementing heavy work in GUI applications; multithreading is now becoming available on more and more platforms, and we expect that zero-millisecond QTimers will gradually be replaced by QThreads.Accuracy and Timer Resolution
Timers will never time out earlier than the specified timeout value and they are not guaranteed to time out at the exact value specified. In many situations, they may time out late by a period of time that depends on the accuracy of the system timers.
The accuracy of timers depends on the underlying operating system and hardware. Most platforms support a resolution of 1 millisecond, though the accuracy of the timer will not equal this resolution in many real-world situations.
If Qt is unable to deliver the requested number of timer clicks, it will silently discard some.
Alternatives to QTimer
An alternative to using QTimer is to call QObject::startTimer() for your object and reimplement the QObject::timerEvent() event handler in your class (which must inherit QObject). The disadvantage is that timerEvent() does not support such high-level features as single-shot timers or signals.
Another alternative to using QTimer is to use QBasicTimer. It is typically less cumbersome than using QObject::startTimer() directly. See Timers for an overview of all three approaches.
Some operating systems limit the number of timers that may be used; Qt tries to work around these limitations.
See also QBasicTimer, QTimerEvent, QObject::timerEvent(), Timers, Analog Clock Example, and Wiggly Example.
Property Documentation
active : const bool
This boolean property is true if the timer is running; otherwise false.
This property was introduced in Qt 4.3.
Access functions:
interval : int
This property holds the timeout interval in milliseconds.
The default value for this property is 0. A QTimer with a timeout interval of 0 will time out as soon as all the events in the window system's event queue have been processed.
Setting the interval of an active timer changes its timerId().
Access functions:
int | interval() const |
void | setInterval(int msec) |
Qt Call Slot From Another Thread
See also singleShot.
singleShot : bool
This property holds whether the timer is a single-shot timer. Queen of the game ep 1.
A single-shot timer fires only once, non-single-shot timers fire every interval milliseconds.
Access functions:
bool | isSingleShot() const |
void | setSingleShot(bool singleShot) |
See also interval and singleShot().
Member Function Documentation
QTimer::QTimer(QObject * parent = 0)
Constructs a timer with the given parent.
QTimer::~QTimer()
Destroys the timer.
[static]
void QTimer::singleShot(int msec, QObject * receiver, const char * member)
This static function calls a slot after a given time interval.
It is very convenient to use this function because you do not need to bother with a timerEvent or create a local QTimer object.
Example:
This sample program automatically terminates after 10 minutes (600,000 milliseconds).
The receiver is the receiving object and the member is the slot. The time interval is msec milliseconds.
Note: This function is reentrant.
See also setSingleShot() and start().
[slot]
void QTimer::start(int msec)
Starts or restarts the timer with a timeout interval of msec milliseconds.
If the timer is already running, it will be stopped and restarted.
If singleShot is true, the timer will be activated only once.
[slot]
void QTimer::start()
This function overloads start().
Starts or restarts the timer with the timeout specified in interval.
If the timer is already running, it will be stopped and restarted.
If singleShot is true, the timer will be activated only once.
[slot]
void QTimer::stop()
Stops the timer.
See also start().
Qt Call Slot In Another Thread
[signal]
void QTimer::timeout()
This signal is emitted when the timer times out.
See also interval, start(), and stop().
[virtual protected]
void QTimer::timerEvent(QTimerEvent * e)
Reimplemented from QObject::timerEvent().
int QTimer::timerId() const
Returns the ID of the timer if the timer is running; otherwise returns -1.
© 2016 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.