Класс QThread
Класс QThread предоставляет платформенно-независимый способ управления потоками. Подробнее...
| Заголовок: | #include <QThread> |
| qmake: | QT += core |
| Наследуется от: | QObject |
Типы публичного доступа
| Перечисление | Priority { IdlePriority, LowestPriority, LowPriority, NormalPriority, ..., InheritPriority } |
Функции публичного доступа
| QThread(QObject *parent = Q_NULLPTR) | |
| ~QThread() | |
| QAbstractEventDispatcher * | eventDispatcher() const |
| void | exit(int returnCode = 0) |
| bool | isFinished() const |
| bool | isInterruptionRequested() const |
| bool | isRunning() const |
| int | loopLevel() const |
| Priority | priority() const |
| void | requestInterruption() |
| void | setEventDispatcher(QAbstractEventDispatcher *eventDispatcher) |
| void | setPriority(Priority priority) |
| void | setStackSize(uint stackSize) |
| uint | stackSize() const |
| bool | wait(unsigned long time = ULONG_MAX) |
Переопределённые функции публичного доступа
| virtual bool | event(QEvent *event) |
- 32 функции публичного доступа унаследованы от QObject
Слот публичного доступа
| void | quit() |
| void | start(Priority priority = InheritPriority) |
| void | terminate() |
- 1 слот публичного доступа унаследован от QObject
Сигналы
| void | finished() |
| void | started() |
- 2 сигнала унаследованы от QObject
Статические члены публичного доступа
| QThread * | currentThread() |
| Qt::HANDLE | currentThreadId() |
| int | idealThreadCount() |
| void | msleep(unsigned long msecs) |
| void | sleep(unsigned long secs) |
| void | usleep(unsigned long usecs) |
| void | yieldCurrentThread() |
- 11 статических членов публичного доступа унаследованы от QObject
Защищённые функции
| int | exec() |
| virtual void | run() |
- 9 защищённых функций унаследованы от QObject
Статические защищённые члены
| void | setTerminationEnabled(bool enabled = true) |
Дополнительные унаследованные члены
- 1 свойство унаследовано от QObject
Подробное описание
Класс QThread предоставляет платформенно-независимый способ управления потоками.
Объект QThread управляет одним потоком управления в программе. Потоки QThread начинают выполнение в run(). По умолчанию, run() запускает цикл событий, вызывая exec(), и выполняет цикл событий Qt внутри потока.
Вы можете использовать рабочие объекты, перемещая их в поток с помощью QObject::moveToThread().
class Worker : public QObject
{
Q_OBJECT
public slots:
void doWork(const QString ¶meter) {
QString result;
/* ... here is the expensive or blocking operation ... */
emit resultReady(result);
}
signals:
void resultReady(const QString &result);
};
class Controller : public QObject
{
Q_OBJECT
QThread workerThread;
public:
Controller() {
Worker *worker = new Worker;
worker->moveToThread(&workerThread);
connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
connect(this, &Controller::operate, worker, &Worker::doWork);
connect(worker, &Worker::resultReady, this, &Controller::handleResults);
workerThread.start();
}
~Controller() {
workerThread.quit();
workerThread.wait();
}
public slots:
void handleResults(const QString &);
signals:
void operate(const QString &);
}; Код внутри слота Рабочего объекта затем будет выполняться в отдельном потоке. Однако вы можете свободно подключить слоты Рабочего объекта к любому сигналу от любого объекта в любом потоке. Безопасно подключать сигналы и слоты между различными потоками благодаря механизму, называемому подключением в очереди.
Другой способ выполнить код в отдельном потоке — это наследование от QThread и переопределение run(). Например:
class WorkerThread : public QThread
{
Q_OBJECT
void run() override {
QString result;
/* ... here is the expensive or blocking operation ... */
emit resultReady(result);
}
signals:
void resultReady(const QString &s);
};
void MyObject::startWorkInAThread()
{
WorkerThread *workerThread = new WorkerThread(this);
connect(workerThread, &WorkerThread::resultReady, this, &MyObject::handleResults);
connect(workerThread, &WorkerThread::finished, workerThread, &QObject::deleteLater);
workerThread->start();
} В этом примере поток завершит свою работу после возврата из функции run. В потоке не будет цикла событий, если вы не вызовете exec().
Важно помнить, что экземпляр QThread находится в старом потоке, в котором он был создан, а не в новом потоке, вызывающем run(). Это означает, что все очереди слотов QThread будут выполняться в старом потоке. Таким образом, разработчик, который хочет вызвать слоты в новом потоке, должен использовать подход с рабочими объектами; новые слоты не должны быть реализованы непосредственно в подклассе QThread.
При наследовании от QThread имейте в виду, что конструктор выполняется в старом потоке, а run() — в новом. Если к члену переменной обращаются из обеих функций, то к переменной обращаются из двух разных потоков. Проверьте, безопасно ли это делать.
Примечание: Нужно проявлять осторожность при взаимодействии с объектами в разных потоках. Подробности см. в разделе Синхронизация потоков.
Управление потоками
QThread уведомит вас о том, что поток был запущен() и завершён() с помощью сигнала, или вы можете использовать isFinished() и isRunning() для запроса состояния потока.
Вы можете остановить поток, вызвав exit() или quit(). В крайних случаях вы можете принудительно прервать выполняющийся поток. Однако это опасно и не рекомендуется. Подробную информацию см. в документации для terminate() и setTerminationEnabled().
Начиная с Qt 4.8, можно освобождать объекты, живущие в только что завершенном потоке, подключив сигнал finished() к QObject::deleteLater().
Используйте wait(), чтобы заблокировать вызывающий поток до тех пор, пока другой поток не завершит выполнение (или пока не истечёт указанное время).
QThread также предоставляет статические, платформенно-независимые функции сна: sleep(), msleep() и usleep() позволяют, соответственно, установить таймеры на полные секунды, миллисекунды и микросекунды. Эти функции были сделаны общедоступными в Qt 5.0.
Примечание: wait() и sleep() функции, как правило, не нужны, поскольку Qt — это фреймворк на основе событий. Вместо wait() следует рассмотреть прослушивание сигнала finished(). Вместо функций sleep() можно использовать QTimer.
Статические функции currentThreadId() и currentThread() возвращают идентификаторы текущей выполняющейся нити. Первая возвращает платформозависимый идентификатор нити; последняя возвращает указатель на QThread.
Чтобы задать имя вашей нити (как определяется командой ps -L на Linux, например), можно вызвать setObjectName() перед запуском нити. Если вы не вызываете setObjectName(), имя вашей нити будет именем класса типа вашей нити во время выполнения (например, "RenderThread" в случае примера Mandelbrot Example, так как это имя подкласса QThread). Обратите внимание, что это в настоящее время недоступно в релизных сборках на Windows.
См. также Поддержка потоков в Qt, QThreadStorage, Синхронизация потоков, Пример Mandelbrot, Пример семафоров и Пример условий ожидания.
Документация по типам членов
enum QThread::Priority
Этот перечислимый тип указывает, как операционная система должна планировать недавно созданные потоки.
| Константа | Значение | Описание |
|---|---|---|
QThread::IdlePriority |
0 |
планируется только тогда, когда другие потоки не выполняются. |
QThread::LowestPriority |
1 |
планируется реже, чем LowPriority. |
QThread::LowPriority |
2 |
планируется реже, чем NormalPriority. |
QThread::NormalPriority |
3 |
стандартный приоритет операционной системы. |
QThread::HighPriority |
4 |
планируется чаще, чем NormalPriority. |
QThread::HighestPriority |
5 |
планируется чаще, чем HighPriority. |
QThread::TimeCriticalPriority |
6 |
планируется как можно чаще. |
QThread::InheritPriority |
7 |
используется тот же приоритет, что и у создающего потока. Это значение по умолчанию. |
Документация по функциям-членам
QThread::QThread(QObject *parent = Q_NULLPTR)
Создает новый QThread для управления новым потоком. parent получает право собственности на QThread. Поток не начинает выполнение до вызова start().
См. также start().
QThread::~QThread()
Удаляет QThread.
Обратите внимание, что удаление объекта QThread не остановит выполнение управляемого им потока. Удаление работающего QThread (т.е. isFinished() возвращает false) приведет к сбою программы. Дождитесь сигнала finished() перед удалением QThread.
[static] QThread *QThread::currentThread()
Возвращает указатель на QThread, который управляет текущим потоком.
[static] Qt::HANDLE QThread::currentThreadId()
Возвращает дескриптор потока текущего выполняющегося потока.
Предупреждение: Дескриптор, возвращаемый этой функцией, используется для внутренних целей и не должен использоваться в коде приложения.
Предупреждение: В Windows возвращаемое значение является псевдодескриптором для текущего потока. Его нельзя использовать для числового сравнения. То есть эта функция возвращает DWORD (ИД потока Windows) возвращаемый функцией Win32 getCurrentThreadId(), а не HANDLE (HANDLE потока Windows) возвращаемый функцией Win32 getCurrentThread().
[virtual] bool QThread::event(QEvent *event)
Переопределено из QObject::event().
QAbstractEventDispatcher *QThread::eventDispatcher() const
Возвращает указатель на объект диспетчера событий для потока. Если для потока диспетчер событий не существует, эта функция возвращает 0.
Эта функция была введена в Qt 5.0.
См. также setEventDispatcher().
[protected] int QThread::exec()
Входит в цикл обработки событий и ожидает, пока не будет вызвано exit(), возвращая значение, которое было передано в exit(). Возвращаемое значение равно 0, если exit() был вызван через quit().
Эта функция предназначена для вызова внутри run(). Для начала обработки событий необходимо вызвать эту функцию.
void QThread::exit(int returnCode = 0)
Сообщает циклу обработки событий потока о завершении с кодом возврата.
После вызова этой функции поток покидает цикл обработки событий и возвращается из вызова QEventLoop::exec(). Функция QEventLoop::exec() возвращает returnCode.
По соглашению, returnCode со значением 0 означает успех, любое ненулевое значение указывает на ошибку.
Обратите внимание, что в отличие от функции C с тем же именем, эта функция возвращает вызывающему абоненту — это обработка событий, которая останавливается.
Никакие циклы QEventLoop больше не будут запускаться в этом потоке до тех пор, пока снова не будет вызван QThread::exec(). Если цикл обработки событий в QThread::exec() не работает, следующий вызов QThread::exec() также вернётся немедленно.
См. также quit() и QEventLoop.
[signal] void QThread::finished()
Этот сигнал испускается из связанного потока непосредственно перед завершением его выполнения.
Когда этот сигнал испускается, цикл обработки событий уже остановлен. Больше событий в потоке обрабатываться не будут, за исключением событий отложенного удаления. Этот сигнал может быть подключен к QObject::deleteLater(), чтобы освободить объекты в этом потоке.
Примечание: Если связанный поток был завершен с помощью terminate(), то из какого потока испускается этот сигнал, не определено.
Примечание: Это частный сигнал. Он может использоваться в соединениях сигналов, но не может испускаться пользователем.
См. также started().
[static] int QThread::idealThreadCount()
Возвращает идеальное количество потоков, которое может выполняться в системе. Это делается с запросом количества процессорных ядер, как реальных, так и логических, в системе. Эта функция возвращает -1, если количество процессорных ядер не может быть определено.
bool QThread::isFinished() const
Возвращает true, если поток завершён; в противном случае возвращает false.
См. также isRunning().
bool QThread::isInterruptionRequested() const
Возвращает true, если задача, выполняемая в этом потоке, должна быть остановлена. Запрос прерывания может быть выполнен с помощью requestInterruption().
Эта функция может быть использована для создания хорошо прерываемых задач с длительным выполнением. Не проверка и не выполнение действий на основании возвращаемого этим значением безопасны, однако рекомендуется делать это регулярно в функциях с длительным выполнением. Будьте осторожны, чтобы не вызывать его слишком часто, чтобы сохранить низкую нагрузку.
void long_task() {
forever {
if ( QThread::currentThread()->isInterruptionRequested() ) {
return;
}
}
} Эта функция была введена в Qt 5.2.
См. также currentThread() и requestInterruption().
bool QThread::isRunning() const
Возвращает true, если поток запущен; в противном случае возвращает false.
См. также isFinished().
int QThread::loopLevel() const
Возвращает текущий уровень цикла обработки событий для потока.
Примечание: Это может быть вызвано только внутри потока, т.е. когда это текущий поток.
Эта функция была введена в Qt 5.5.
[static] void QThread::msleep(unsigned long msecs)
Заставляет текущий поток заснуть на msecs миллисекунд.
Priority QThread::priority() const
Возвращает приоритет запущенного потока. Если поток не запущен, эта функция возвращает InheritPriority.
Эта функция была добавлена в Qt 4.1.
См. также Priority, setPriority() и start().
[slot] void QThread::quit()
Уведомляет цикл событий потока об окончании работы с кодом возврата 0 (успех). Эквивалентно вызову QThread::exit(0).
Эта функция ничего не делает, если у потока нет цикла событий.
См. также exit() и QEventLoop.
void QThread::requestInterruption()
Запрашивает прерывание потока. Это запрос, и код, выполняющийся в потоке, сам решает, как и нужно ли реагировать на такой запрос. Эта функция не останавливает ни один цикл событий, выполняющийся в потоке, и не завершает его каким-либо образом.
Эта функция была добавлена в Qt 5.2.
См. также isInterruptionRequested().
[virtual protected] void QThread::run()
Точка входа для потока. После вызова start() новый поток вызывает эту функцию. По умолчанию она просто вызывает exec().
Вы можете переопределить эту функцию для более сложного управления потоками. Возврат из этой функции завершит выполнение потока.
void QThread::setEventDispatcher(QAbstractEventDispatcher *eventDispatcher)
Устанавливает диспетчер событий для потока в eventDispatcher. Это возможно только до тех пор, пока для потока еще нет установленного диспетчера событий. То есть, до запуска потока с помощью start() или, в случае основного потока, до создания экземпляра QCoreApplication. Этот метод принимает владение объектом.
Эта функция была добавлена в Qt 5.0.
См. также eventDispatcher().
void QThread::setPriority(Priority priority)
Эта функция устанавливает priority для запущенного потока. Если поток не запущен, эта функция ничего не делает и возвращается немедленно. Используйте start(), чтобы запустить поток с определенным приоритетом.
Аргумент priority может принимать любое значение в перечислении QThread::Priority, кроме InheritPriorty.
Эффект параметра priority зависит от политики планирования операционной системы. В частности, priority будет игнорироваться на системах, не поддерживающих приоритеты потоков (например, на Linux, см. http://linux.die.net/man/2/sched_setscheduler для получения дополнительных сведений).
Эта функция была добавлена в Qt 4.1.
См. также Priority, priority() и start().
void QThread::setStackSize(uint stackSize)
Устанавливает максимальный размер стека для потока в stackSize. Если stackSize больше нуля, максимальный размер стека устанавливается в stackSize байтов, в противном случае максимальный размер стека автоматически определяется операционной системой.
Предупреждение: Большинство операционных систем устанавливают минимальные и максимальные ограничения на размеры стека потока. Поток не сможет запуститься, если размер стека выходит за эти пределы.
См. также stackSize().
[static protected] void QThread::setTerminationEnabled(bool enabled = true)
Включает или выключает завершение текущего потока в зависимости от параметра enabled. Поток должен был быть запущен с помощью QThread.
Когда enabled равно false, завершение отключено. Будущие вызовы QThread::terminate() вернутся немедленно без эффекта. Вместо этого завершение откладывается до включения завершения.
Когда enabled равно true, завершение включено. Будущие вызовы QThread::terminate() завершат поток обычным способом. Если завершение было отложено (т.е. QThread::terminate() был вызван с отключенным завершением), эта функция завершит вызывающий поток немедленно. Обратите внимание, что в этом случае функция не вернётся.
См. также terminate().
[static] void QThread::sleep(unsigned long secs)
Принудительно останавливает текущий поток на secs секунд.
См. также msleep() и usleep().
uint QThread::stackSize() const
Возвращает максимальный размер стека для потока (если он был установлен с помощью setStackSize()); в противном случае возвращает ноль.
См. также setStackSize().
[slot] void QThread::start(Priority priority = InheritPriority)
Начинает выполнение потока, вызывая run(). Операционная система будет планировать поток в соответствии с параметром priority. Если поток уже запущен, эта функция ничего не делает.
Эффект параметра priority зависит от политики планирования операционной системы. В частности, priority будет игнорироваться на системах, не поддерживающих приоритеты потоков (например, на Linux, см. документацию к sched_setscheduler для получения дополнительных сведений).
См. также run() и terminate().
[signal] void QThread::started()
Этот сигнал испускается из связанного потока при его запуске, до вызова функции run().
Примечание: Это закрытый сигнал. Он может быть использован в соединениях сигналов, но не может быть испущен пользователем.
См. также finished().
[slot] void QThread::terminate()
Завершает выполнение потока. Поток может быть завершен немедленно или нет, в зависимости от политики планирования операционной системы. Используйте QThread::wait() после terminate(), чтобы быть уверенным.
Когда поток завершен, все потоки, ожидающие завершения потока, будут разбужены.
Предупреждение: Эта функция небезопасна, и её использование не рекомендуется. Поток может быть завершен в любой точке своего пути кода. Потоки могут быть завершены во время изменения данных. Поток не имеет возможности очистить за собой, разблокировать любые захваченные мьютексы и т.д. Короче говоря, используйте эту функцию только если это абсолютно необходимо.
Завершение может быть явно включено или выключено путём вызова QThread::setTerminationEnabled(). Вызов этой функции, когда завершение отключено, приводит к отложению завершения до повторного включения. См. документацию к QThread::setTerminationEnabled() для получения дополнительной информации.
См. также setTerminationEnabled().
[static] void QThread::usleep(unsigned long usecs)
Принудительно останавливает текущий поток на usecs микросекунд.
bool QThread::wait(unsigned long time = ULONG_MAX)
Задерживает поток, пока не будет выполнено одно из следующих условий:
- Поток, связанный с этим объектом QThread, завершил выполнение (т.е. когда он возвращается из run()). Эта функция вернёт true, если поток завершился. Она также вернёт true, если поток ещё не был запущен.
- Прошло time миллисекунд. Если time равно ULONG_MAX (значение по умолчанию), ожидание никогда не истечёт (поток должен вернуться из run()). Эта функция вернёт false, если ожидание истекло.
Это обеспечивает функциональность, аналогичную функции POSIX pthread_join().
См. также sleep() и terminate().
[static] void QThread::yieldCurrentThread()
Уступает выполнение текущего потока другому исполняемому потоку, если таковой имеется. Обратите внимание, что операционная система решает, в какой поток переключиться.
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-5.9/qthread.html