Spec-Zone.ru › Qt

Класс QThread

Класс QThread предоставляет платформонезависимый способ управления потоками. Подробнее...

Заголовок: #include <QThread>
CMake: find_package(Qt6 COMPONENTS Core REQUIRED) target_link_libraries(mytarget PRIVATE Qt6::Core)
qmake: QT += core
Наследует: QObject
  • Список всех членов, включая унаследованные

Типы публичного доступа

Перечисление Priority { IdlePriority, LowestPriority, LowPriority, NormalPriority, HighPriority, …, InheritPriority }

Функции публичного доступа

QThread(QObject *parent = nullptr)
virtual ~QThread()
QAbstractEventDispatcher * eventDispatcher() const
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)

Переопределённые функции публичного доступа

virtual bool event(QEvent *event) override

Свойства публичного доступа

void exit(int returnCode = 0)
void quit()
void start(QThread::Priority priority = InheritPriority)
void terminate()

Сигналы

void finished()
void started()

Статические члены публичного доступа

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 &parameter) {
        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 &);
};

Код внутри слота Worker затем будет выполняться в отдельном потоке. Однако вы можете свободно подключать слоты Worker к любому сигналу из любого объекта в любом потоке. Подключение сигналов и слотов через разные потоки безопасно благодаря механизму, называемому потокобезопасными подключениями.

Другой способ запустить код в отдельном потоке — наследование от 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, так как это имя подкласса 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().

[slot] void QThread::exit(int returnCode = 0)

Указывает циклу событий нити на выход с кодом возврата.

После вызова этой функции нить покидает цикл событий и возвращается из вызова QEventLoop::exec(). Функция QEventLoop::exec() возвращает returnCode.

По соглашению, returnCode со значением 0 означает успех, любое ненулевое значение указывает на ошибку.

Обратите внимание, что в отличие от одноименной функции C-библиотеки, эта функция возвращается вызывающему объекту — останавливается обработка событий.

Больше циклов QEventLoops не будут запускаться в этой нити до тех пор, пока не будет вызван QThread::exec(). Если цикл событий в QThread::exec() не работает, то следующий вызов QThread::exec() также вернет сразу.

Примечание: Эта функция безопасна для многопоточного доступа.

См. также quit() и QEventLoop.

[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(). Необходимо вызвать эту функцию, чтобы начать обработку событий.

Примечание: Это можно вызвать только внутри самого потока, т.е. когда это текущий поток.

См. также quit() и exit().

[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 мс.

См. также sleep() и usleep().

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().

Вы можете переопределить эту функцию для реализации сложной обработки потоков. Возврат из этой функции завершает выполнение потока.

См. также start() и wait().

[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 мс.

См. также sleep() и msleep().

[since 5.15] 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)

Это перегруженная функция.

time — время ожидания в миллисекундах. Если time равно ULONG_MAX, ожидание никогда не истечёт.

[static] void QThread::yieldCurrentThread()

Уступает выполнение текущего потока другому исполняемому потоку, если таковой имеется. Обратите внимание, что операционная система решает, какой поток переключиться.

© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-6.2/qthread.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API