Класс QThread
Класс QThread предоставляет платформенно-независимый способ управления потоками. Подробнее...
| Заголовок: | #include <QThread> |
| qmake: | QT += core |
| Наследует: | QObject |
Типы public
| Перечисление | Priority { IdlePriority, LowestPriority, LowPriority, NormalPriority, HighPriority, …, InheritPriority } |
Функции public
| QThread(QObject *parent = nullptr) | |
| virtual | ~QThread() |
| QAbstractEventDispatcher * | eventDispatcher() const |
| void | exit(int returnCode = 0) |
| bool | isFinished() const |
| bool | isInterruptionRequested() const |
| bool | isRunning() const |
| int | loopLevel() const |
| QThread::Priority | priority() const |
| void | requestInterruption() |
| void | setEventDispatcher(QAbstractEventDispatcher *eventDispatcher) |
| void | setPriority(QThread::Priority priority) |
| void | setStackSize(uint stackSize) |
| uint | stackSize() const |
| bool | wait(QDeadlineTimer deadline = QDeadlineTimer(QDeadlineTimer::Forever)) |
| bool | wait(unsigned long time) |
Переопределенные функции public
| virtual bool | event(QEvent *event) override |
Свойства public
| void | quit() |
| void | start(QThread::Priority priority = InheritPriority) |
| void | terminate() |
Сигналы
| void | finished() |
| void | started() |
Статические члены public
| QThread * | create(Function &&f, Args &&... args) |
| QThread * | create(Function &&f) |
| QThread * | currentThread() |
| Qt::HANDLE | currentThreadId() |
| int | idealThreadCount() |
| void | msleep(unsigned long msecs) |
| void | sleep(unsigned long secs) |
| void | usleep(unsigned long usecs) |
| void | yieldCurrentThread() |
Защищенные функции
| int | exec() |
| virtual void | run() |
Статические защищенные члены
| void | setTerminationEnabled(bool enabled = true) |
Подробное описание
Объект QThread управляет одним потоком управления в программе. QThreads начинают выполнение в 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, будут выполняться в потоке, который вызывает метод. При наследовании QThread имейте в виду, что конструктор выполняется в старом потоке, а run() выполняется в новом потоке. Если член переменной доступен из обеих функций, то переменная доступна из двух разных потоков. Убедитесь, что это безопасно.
Примечание: При взаимодействии с объектами в разных потоках необходимо соблюдать осторожность. Как общее правило, функции могут быть вызваны только из потока, который создал сам объект QThread (например, setPriority()), если документация не указывает обратного. Подробности см. в разделе Синхронизация потоков.
Управление потоками
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" в случае примера Мандельброта, поскольку это имя подкласса QThread). Обратите внимание, что в настоящее время это недоступно в релизных сборках на Windows.
См. также Поддержка потоков в Qt, QThreadStorage, Синхронизация потоков, Пример Мандельброта, Пример семафоров и Пример условий ожидания.
Документация по типам членов
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 = nullptr)
Создает новый QThread для управления новым потоком. parent получает владение QThread. Поток не начинает выполнение до вызова start().
См. также start().
[signal] void QThread::finished()
Этот сигнал испускается из связанного потока непосредственно перед его завершением.
При испускании этого сигнала цикл событий уже остановлен. В потоке больше не будут обрабатываться события, кроме событий отложенного удаления. Этот сигнал может быть подключен к QObject::deleteLater(), чтобы освободить объекты в этом потоке.
Примечание: Если связанный поток был завершен с помощью terminate(), то от какого потока испускается этот сигнал, неопределено.
Примечание: Это частный сигнал. Он может использоваться в подключении сигналов, но не может испускаться пользователем.
См. также started().
[slot] void QThread::quit()
Уведомляет цикл событий потока о завершении с кодом возврата 0 (успех). Эквивалентно вызову QThread::exit(0).
Эта функция ничего не делает, если поток не имеет цикла событий.
Примечание: Эта функция безопасна для потоков.
См. также exit() и QEventLoop.
[slot] void QThread::start(QThread::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().
[virtual] QThread::~QThread()
Удаляет QThread.
Обратите внимание, что удаление объекта QThread не остановит выполнение управляемого им потока. Удаление работающего QThread (т. е. isFinished() возвращает false) приведет к сбою программы. Дождитесь сигнала finished() перед удалением QThread.
[static] template <typename Function, typename Args> QThread *QThread::create(Function &&f, Args &&... args)
Создает новый объект QThread, который будет выполнять функцию f с аргументами args.
Новый поток не запускается — его необходимо запустить явным вызовом start(). Это позволяет подключиться к его сигналам, перемещать QObjects в поток, выбирать приоритет нового потока и т. д. Функция f будет вызвана в новом потоке.
Возвращает созданный экземпляр QThread.
Примечание: вызывающая сторона получает владение возвращенным экземпляром QThread.
Примечание: эта функция доступна только при использовании C++17.
Предупреждение: не вызывайте start() для возвращенного экземпляра QThread более одного раза; это приведет к неопределенному поведению.
Эта функция была добавлена в Qt 5.10.
См. также start().
[static] template <typename Function> QThread *QThread::create(Function &&f)
Создает новый объект QThread, который будет выполнять функцию f.
Новый поток не запускается — его необходимо запустить явным вызовом start(). Это позволяет подключиться к его сигналам, перемещать QObjects в поток, выбирать приоритет нового потока и т. д. Функция f будет вызвана в новом потоке.
Возвращает созданный экземпляр QThread.
Примечание: вызывающая сторона получает владение возвращенным экземпляром QThread.
Предупреждение: не вызывайте start() для возвращенного экземпляра QThread более одного раза; это приведет к неопределенному поведению.
Эта функция была добавлена в Qt 5.10.
См. также start().
[static] QThread *QThread::currentThread()
Возвращает указатель на QThread, который управляет текущим исполняемым потоком.
[static] Qt::HANDLE QThread::currentThreadId()
Возвращает дескриптор потока текущего исполняемого потока.
Предупреждение: Дескриптор, возвращаемый этой функцией, используется для внутренних целей и не должен использоваться в коде приложения.
Примечание: В Windows эта функция возвращает DWORD (ID потока Windows), возвращаемый функцией Win32 GetCurrentThreadId(), а не псевдо-HANDLE (HANDLE потока Windows), возвращаемый функцией Win32 GetCurrentThread().
[override virtual] bool QThread::event(QEvent *event)
Переопределяет: QObject::event(QEvent *e).
QAbstractEventDispatcher *QThread::eventDispatcher() const
Возвращает указатель на объект диспетчера событий для потока. Если для потока нет диспетчера событий, эта функция возвращает nullptr.
Эта функция была добавлена в 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.
[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 миллисекунд.
Избегайте использования этой функции, если вам нужно дождаться изменения определённого условия. Вместо этого подключите слот к сигналу, который указывает на изменение, или используйте обработчик событий (см. QObject::event()).
Примечание: Эта функция не гарантирует точности. При высокой нагрузке приложение может заснуть дольше, чем msecs. Некоторые ОС могут округлять msecs до 10 мс или 15 мс.
QThread::Priority QThread::priority() const
Возвращает приоритет выполняющегося потока. Если поток не выполняется, эта функция возвращает InheritPriority.
Эта функция была добавлена в Qt 4.1.
См. также Priority, setPriority() и start().
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(QThread::Priority priority)
Эта функция устанавливает priority для выполняющегося потока. Если поток не выполняется, эта функция ничего не делает и возвращается сразу. Используйте start() для запуска потока с определённым приоритетом.
Аргумент priority может принимать любое значение в перечислении QThread::Priority за исключением InheritPriority.
Эффект параметра 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 секунд.
Избегайте использования этой функции, если вам нужно дождаться изменения заданного условия. Вместо этого подключите слот к сигналу, указывающему на изменение, или используйте обработчик событий (см. QObject::event()).
Примечание: Эта функция не гарантирует точности. При высокой нагрузке приложение может спать дольше, чем secs.
См. также msleep() и usleep().
uint QThread::stackSize() const
Возвращает максимальный размер стека для потока (если он был задан с помощью setStackSize()); в противном случае возвращает ноль.
См. также setStackSize().
[static] void QThread::usleep(unsigned long usecs)
Принудительно останавливает текущий поток на usecs микросекунд.
Избегайте использования этой функции, если вам нужно дождаться изменения заданного условия. Вместо этого подключите слот к сигналу, указывающему на изменение, или используйте обработчик событий (см. QObject::event()).
Примечание: Эта функция не гарантирует точности. При высокой нагрузке приложение может спать дольше, чем usecs. Некоторые операционные системы могут округлять usecs до 10 мс или 15 мс; в Windows оно будет округляться до кратного 1 мс.
bool QThread::wait(QDeadlineTimer deadline = QDeadlineTimer(QDeadlineTimer::Forever))
Блокирует поток, пока не будет выполнено одно из этих условий:
- Поток, связанный с этим объектом QThread, завершил выполнение (т. е. когда он возвращается из run()). Эта функция вернет true, если поток завершился. Она также вернет true, если поток еще не был запущен.
- Срок deadline истек. Эта функция вернет false, если срок истек.
Таймер с датой истечения, установленный в QDeadlineTimer::Forever (по умолчанию), никогда не истечет: в этом случае функция возвращается только при возвращении потока из run() или если поток еще не был запущен.
Это предоставляет функциональность, аналогичную функции POSIX pthread_join().
Эта функция была введена в Qt 5.15.
См. также sleep() и terminate().
bool QThread::wait(unsigned long time)
Это перегруженная функция.
[static] void QThread::yieldCurrentThread()
Уступает выполнение текущего потока другому выполнимому потоку, если таковой имеется. Обратите внимание, что операционная система решает, какому потоку переключиться.
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-5.15/qthread.html