Класс QThread
Класс QThread предоставляет платформенно-независимый способ управления потоками. Подробнее...
| Заголовок: | #include <QThread> |
| qmake: | QT += core |
| Наследует: | QObject |
Открытые типы
| Перечисление | Priority { IdlePriority, LowestPriority, LowPriority, NormalPriority, ..., InheritPriority } |
Открытые функции
| 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(unsigned long time = ULONG_MAX) |
Переопределённые открытые функции
| virtual bool | event(QEvent *event) override |
- 32 открытых функции, унаследованные от QObject
Открытые слоты
| void | quit() |
| void | start(QThread::Priority priority = InheritPriority) |
| void | terminate() |
- 1 открытый слот, унаследованный от QObject
Сигналы
| void | finished() |
| void | started() |
- 2 сигнала, унаследованные от QObject
Статические открытые члены
| 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() |
- 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, будут выполняться в потоке, который вызвал метод. При наследовании от QThread, имейте в виду, что конструктор выполняется в старом потоке, а run() — в новом. Если к члену переменной обращаются из обеих функций, то к переменной обращаются из двух разных потоков. Убедитесь, что это безопасно.
Примечание: Следует проявлять осторожность при взаимодействии с объектами в разных потоках. Подробности см. в разделе Синхронизация потоков.
Управление потоками
QThread уведомит вас о том, что поток запущен() и завершен(), или вы можете использовать isFinished() и isRunning() для запроса состояния потока.
Вы можете остановить поток, вызвав exit() или quit(). В крайних случаях вы можете принудительно прервать работающий поток. Однако делать это опасно и не рекомендуется. Обратитесь к документации для terminate() и setTerminationEnabled() для получения подробной информации.
Начиная с Qt 4.8, можно освободить объекты, которые живут в потоке, который только что завершился, подключив сигнал finished() к QObject::deleteLater().
END_OF_DOCUMENT_MARKERИспользуйте wait() для блокировки вызывающей потока, пока другой поток не завершит выполнение (или пока не пройдёт заданное время).
QThread также предоставляет статические, независимые от платформы функции сна: sleep(), msleep() и usleep() соответственно с разрешением в секунды, миллисекунды и микросекунды. Эти функции были сделаны общедоступными в Qt 5.0.
Примечание: wait() и функции sleep() в общем случае должны быть не нужны, так как Qt является фреймворком на основе событий. Вместо wait() рассмотрите возможность прослушивания сигнала finished(). Вместо функций sleep() рассмотрите использование QTimer.
Статические функции currentThreadId() и currentThread() возвращают идентификаторы текущего выполняемого потока. Первая возвращает специфичный для платформы ID потока; вторая возвращает указатель QThread.
Чтобы выбрать имя, которое получит ваш поток (как идентифицируется командой ps -L на Linux, например), вы можете вызвать setObjectName() перед запуском потока. Если вы не вызываете setObjectName(), имя, присваиваемое потоку, будет именем класса типа runtime вашего объекта потока (например, "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 = nullptr)
Создаёт новый QThread для управления новым потоком. parent получает владение QThread. Поток не начинает выполнение до вызова start().
См. также start().
[virtual] QThread::~QThread()
Удаляет QThread.
Обратите внимание, что удаление объекта QThread не остановит выполнение управляемого им потока. Удаление работающего QThread (т.е. isFinished() возвращает false) приведёт к сбою программы. Дождитесь сигнала finished() перед удалением QThread.
[static] QThread *QThread::create(Function &&f, Args &&... args)
Создаёт новый объект QThread, который будет выполнять функцию f с аргументами args.
Новый поток не запускается — его необходимо запустить явным вызовом start(). Это позволяет подключиться к его сигналам, переместить QObjects в поток, выбрать приоритет нового потока и так далее. Функция f будет вызвана в новом потоке.
Возвращает созданный экземпляр QThread.
Примечание: вызывающий код получает владение возвращённым экземпляром QThread.
Примечание: эта функция доступна только при использовании C++17.
Предупреждение: не вызывайте start() для возвращённого экземпляра QThread более одного раза; это приведёт к неопределённому поведению.
Эта функция была добавлена в Qt 5.10.
См. также start().
[static] 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 (дескриптор потока Windows), возвращаемое функцией Win32 getCurrentThread().
[override 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(), то от какого потока излучается этот сигнал, неопределено.
Примечание: Это частный сигнал. Его можно использовать в подключениях сигнала, но его нельзя излучить пользователем.
END_OF_DOCUMENT_MARKERСм. также 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 миллисекунд.
QThread::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(QThread::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(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().
[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/archives/qt-5.11/qthread.html