Doc: Update QThread class ref to reflect changes since Qt 4.4

Remove advice to subclass QThread; promote thinking of QThread as a
thread manager, not a thread; promote event-driven programming over time
micromanagement; warn against common pitfalls.

Result of collaboration in forum (https://qt-project.org/forums/viewthread/20691/)
and mailing list (https://qt-project.org/pipermail/development/2012-September/006738.html)

Task-number: QTBUG-16358
Change-Id: I57e3873976fad489176cbf9f7e680fd6992a8837
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@digia.com>
bb10
Sze Howe Koh 2012-10-04 19:33:39 +08:00 committed by The Qt Project
parent bac9d5921f
commit d4ad9dbbf9
2 changed files with 132 additions and 61 deletions

View File

@ -39,18 +39,40 @@
****************************************************************************/
//! [0]
class MyThread : public QThread
class Worker : public QObject
{
public:
void run();
Q_OBJECT
public slots:
void doWork() {
...
}
};
void MyThread::run()
void MyObject::putWorkerInAThread()
{
QTcpSocket socket;
// connect QTcpSocket's signals somewhere meaningful
...
socket.connectToHost(hostName, portNumber);
exec();
Worker *worker = new Worker;
QThread *workerThread = new QThread(this);
connect(workerThread, &QThread::started, worker, &Worker::doWork);
connect(workerThread, &QThread::finished, worker, &Worker::deleteLater);
worker->moveToThread(workerThread);
// Starts an event loop, and emits workerThread->started()
workerThread->start();
}
//! [0]
//! [1]
class AdvancedThreadManager : public QThread
{
protected:
void run()
{
/* ... other code to initialize thread... */
// Begin event handling
exec();
}
};
//! [1]

View File

@ -172,58 +172,100 @@ QThreadPrivate::~QThreadPrivate()
/*!
\class QThread
\inmodule QtCore
\brief The QThread class provides platform-independent threads.
\brief The QThread class provides a platform-independent way to
manage threads.
\ingroup thread
A QThread represents a separate thread of control within the
program; it shares data with all the other threads within the
process but executes independently in the way that a separate
program does on a multitasking operating system. Instead of
starting in \c main(), QThreads begin executing in run(). By
default, run() starts the event loop by calling exec() (see
below). To create your own threads, subclass QThread and
reimplement run(). For example:
A QThread object manages one thread of control within the
program. To make code run in a separate thread, simply create a
QThread, change the thread affinity of the QObject(s) that
contain the code, and start() the new event loop. For example:
\snippet code/src_corelib_thread_qthread.cpp 0
This will create a QTcpSocket in the thread and then execute the
thread's event loop. Use the start() method to begin execution.
Execution ends when you return from run(), just as an application
does when it leaves main(). QThread will notifiy you via a signal
The code inside the Worker's slot would then execute in a
separate thread. In this example, the QThread triggers the
Worker's doWork() slot upon starting, and frees the Worker's
memory upon terminating. However, you are free to connect the
Worker's slots to any signal, from any object, in any thread. It
is safe to connect signals and slots across different threads,
thanks to a mechanism called \l{Qt::QueuedConnection}{queued
connections}.
\note If you interact with an object, using any technique other
than queued signal/slot connections (e.g. direct function calls),
then the usual multithreading precautions need to be taken.
\note It is not possible to change the thread affinity of GUI
objects; they must remain in the main thread.
\section1 Managing threads
QThread will notifiy you via a signal
when the thread is started(), finished(), and terminated(), or
you can use isFinished() and isRunning() to query the state of
the thread. Use wait() to block until the thread has finished
execution.
the thread.
Each thread gets its own stack from the operating system. The
operating system also determines the default size of the stack.
You can use setStackSize() to set a custom stack size.
You can stop the thread by calling exit() or quit(). In extreme
cases, you may want to forcibly terminate() an executing thread.
However, doing so is dangerous and discouraged. Please read the
documentation for terminate() and setTerminationEnabled() for
detailed information.
Each QThread can have its own event loop. You can start the event
loop by calling exec(); you can stop it by calling exit() or
quit(). Having an event loop in a thread makes it possible to
connect signals from other threads to slots in this thread, using
a mechanism called \l{Qt::QueuedConnection}{queued
connections}. It also makes it possible to use classes that
require the event loop, such as QTimer and QTcpSocket, in the
thread. Note, however, that it is not possible to use any widget
classes in the thread.
From Qt 4.8 onwards, it is possible to deallocate objects that
live in a thread that has just ended, by connecting the
finished() signal to QObject::deleteLater().
In extreme cases, you may want to forcibly terminate() an
executing thread. However, doing so is dangerous and discouraged.
Please read the documentation for terminate() and
setTerminationEnabled() for detailed information.
Use wait() to block the calling thread, until the other thread
has finished execution (or until a specified time has passed).
QThread also provides static, platform independent sleep
functions: sleep(), msleep(), and usleep() allow full second,
millisecond, and microsecond resolution respectively. These
functions were made public in Qt 5.0.
\note wait() and the sleep() functions should be unnecessary in
general, since Qt is an event-driven framework. Instead of
wait(), consider listening for the finished() signal. Instead of
the sleep() functions, consider using QTimer.
The static functions currentThreadId() and currentThread() return
identifiers for the currently executing thread. The former
returns a platform specific ID for the thread; the latter returns
a QThread pointer.
QThread also provides platform independent sleep functions in
varying resolutions. Use sleep() for full second resolution,
msleep() for millisecond resolution, and usleep() for microsecond
resolution.
\section1 Subclassing QThread
Subclassing QThread is unnecessary for most purposes, since
QThread provides fully-functional thread management capabilities.
Nonetheless, QThread can be subclassed if you wish to implement
advanced thread management. This is done by adding new member
functions to the subclass, and/or by reimplementing run().
QThread's run() function is analogous to an application's main()
function -- it is executed when the thread is started, and the
thread will end when it returns.
\note Prior to Qt 4.4, the only way to use QThread for parallel
processing was to subclass it and implement the processing code
inside run(). This approach is now considered \b {bad practice};
a QThread should only manage a thread, not process data.
If you require event handling and signal/slot connections to
work in your thread, and if you reimplement run(), you must
explicitly call exec() at the end of your reimplementation:
\snippet code/src_corelib_thread_qthread.cpp 1
It is important to remember that a QThread object usually lives
in the thread where it was created, not in the thread that it
manages. This oft-overlooked detail means that a QThread's slots
will be executed in the context of its home thread, not in the
context of the thread it is managing. For this reason,
implementing new slots in a QThread subclass is error-prone and
discouraged.
\sa {Thread Support in Qt}, QThreadStorage, QMutex, QSemaphore, QWaitCondition,
{Mandelbrot Example}, {Semaphores Example}, {Wait Conditions Example}
@ -264,8 +306,7 @@ QThreadPrivate::~QThreadPrivate()
/*!
\fn void QThread::start(Priority priority)
Begins execution of the thread by calling run(), which should be
reimplemented in a QThread subclass to contain your code. The
Begins execution of the thread by calling run(). The
operating system will schedule the thread according to the \a
priority parameter. If the thread is already running, this
function does nothing.
@ -328,7 +369,7 @@ QThreadPrivate::~QThreadPrivate()
*/
/*!
Returns a pointer to a QThread which represents the currently
Returns a pointer to a QThread which manages the currently
executing thread.
*/
QThread *QThread::currentThread()
@ -339,8 +380,9 @@ QThread *QThread::currentThread()
}
/*!
Constructs a new thread with the given \a parent. The thread does
not begin executing until start() is called.
Constructs a new QThread to manage a new thread. The \a parent
takes ownership of the QThread. The thread does not begin
executing until start() is called.
\sa start()
*/
@ -364,13 +406,13 @@ QThread::QThread(QThreadPrivate &dd, QObject *parent)
}
/*!
Destroys the thread.
Destroys the QThread.
Note that deleting a QThread object will not stop the execution
of the thread it represents. Deleting a running QThread (i.e.
of the thread it manages. Deleting a running QThread (i.e.
isFinished() returns false) will probably result in a program
crash. You can wait() on a thread to make sure that it has
finished.
crash. Wait for the finished() signal before deleting the
QThread.
*/
QThread::~QThread()
{
@ -527,9 +569,9 @@ void QThread::quit()
newly created thread calls this function. The default
implementation simply calls exec().
You can reimplemented this function to do other useful
work. Returning from this method will end the execution of the
thread.
You can reimplement this function to facilitate advanced thread
management. Returning from this method will end the execution of
the thread.
\sa start(), wait()
*/
@ -586,7 +628,7 @@ QThread::Priority QThread::priority() const
/*!
\fn void QThread::msleep(unsigned long msecs)
Causes the current thread to sleep for \a msecs milliseconds.
Forces the current thread to sleep for \a msecs milliseconds.
\sa sleep(), usleep()
*/
@ -594,7 +636,7 @@ QThread::Priority QThread::priority() const
/*!
\fn void QThread::usleep(unsigned long usecs)
Causes the current thread to sleep for \a usecs microseconds.
Forces the current thread to sleep for \a usecs microseconds.
\sa sleep(), msleep()
*/
@ -603,9 +645,9 @@ QThread::Priority QThread::priority() const
\fn void QThread::terminate()
Terminates the execution of the thread. The thread may or may not
be terminated immediately, depending on the operating systems
scheduling policies. Use QThread::wait() after terminate() for
synchronous termination.
be terminated immediately, depending on the operating system's
scheduling policies. Listen for the terminated() signal, or use
QThread::wait() after terminate(), to be sure.
When the thread is terminated, all threads waiting for the thread
to finish will be woken up.
@ -708,6 +750,8 @@ QThread::QThread(QThreadPrivate &dd, QObject *parent)
#endif // QT_NO_THREAD
/*!
\since 5.0
Returns a pointer to the event dispatcher object for the thread. If no event
dispatcher exists for the thread, this function returns 0.
*/
@ -718,6 +762,8 @@ QAbstractEventDispatcher *QThread::eventDispatcher() const
}
/*!
\since 5.0
Sets the event dispatcher for the thread to \a eventDispatcher. This is
only possible as long as there is no event dispatcher installed for the
thread yet. That is, before the thread has been started with start() or, in
@ -738,6 +784,9 @@ void QThread::setEventDispatcher(QAbstractEventDispatcher *eventDispatcher)
}
}
/*!
\reimp
*/
bool QThread::event(QEvent *event)
{
if (event->type() == QEvent::Quit) {