Класс QThread
Класс QThread предоставляет платформенно-независимый способ управления потоками. Подробнее...
| Заголовок: | #include <QThread> |
| CMake: | find_package(Qt6 COMPONENTS Core REQUIRED) target_link_libraries(mytarget PRIVATE Qt6::Core) |
| 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 * | 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 управляет одним потоком управления в программе. 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 (например, 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() возвращают идентификаторы текущего выполняемого потока. Первая возвращает платформозависимый ID потока; вторая — указатель на QThread.
Чтобы задать имя своему потоку (например, идентифицируемое командой ps -L в Linux), вы можете вызвать setObjectName() перед запуском потока. Если вы не вызываете setObjectName(), имя, присвоенное вашему потоку, будет именем класса исполняемого типа объекта вашего потока (например, "RenderThread" в случае примера Mandelbrot Example, так как это имя подкласса QThread). Обратите внимание, что это в настоящее время недоступно в релизных сборках на Windows.
См. также Поддержка потоков в Qt, QThreadStorage, Синхронизация потоков, Пример Mandelbrot, Пример семафоров и Пример условных переменных ожидания.
Документация типов членов
перечисление 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().
[private 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().
[private 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, since 5.10] template <typename Function, typename Args> QThread *QThread::create(Function &&f, Args &&... args)
Создаёт новый объект QThread, который выполнит функцию f с аргументами args.
Новый поток не запускается — его необходимо запустить с помощью явного вызова 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).
[since 5.0] 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().
[since 5.2] 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().
[since 5.5] 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.
См. также Priority, setPriority() и start().
[since 5.2] void QThread::requestInterruption()
Запросить прерывание потока. Этот запрос рекомендательный, и код, выполняемый в потоке, сам решает, как и нужно ли реагировать на такой запрос. Эта функция не останавливает ни один работающий цикл обработки событий в потоке и не завершает его каким-либо образом.
Примечание: Эта функция безопасна для многопоточности.
Функция была добавлена в Qt 5.2.
См. также isInterruptionRequested().
[virtual protected] void QThread::run()
Точка входа для потока. После вызова start() новый поток вызывает эту функцию. По умолчанию она просто вызывает exec().
Вы можете переопределить эту функцию для управления потоками более сложным образом. Возврат из этого метода завершит выполнение потока.
[since 5.0] 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 для получения дополнительной информации).
См. также 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 мс.
[since 5.15] bool QThread::wait(QDeadlineTimer deadline = QDeadlineTimer(QDeadlineTimer::Forever))
Заблокирует поток до выполнения одного из следующих условий:
- Поток, связанный с объектом QThread, завершил выполнение (т.е. когда он возвращается из run()). Эта функция вернёт true, если поток завершился. Она также вернёт true, если поток ещё не запущен.
- Достигнут deadline. Эта функция вернёт false, если срок действия deadline истек.
Таймер deadline, установленный в 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-6.0/qthread.html