서론

 

QT에서의 Thread를 공식문서와 함께 알아보자

https://doc.qt.io/qt-6/qthread.html#protected-functions

 

QThread Class | Qt Core 6.7.2

 

doc.qt.io


Public Function

반환형 메서드 설명
  QThread(QObject *parent = nullptr) QThread 객체를 생성, 선택적으로 부모 QObject 설정가능
virtual ~QThread() QThread 객체를 소멸, 소멸자가 호출될 때 스레드가 종료되지 않았으면 스레드를 종료
QAbstractEventDispatcher * eventDispatcher() const 현재 스레드의 이벤트 디스패처를 반환
이벤트 디스패처는 이벤트 루프에서 이벤트를 처리하는 역할을 한다.
bool isFinished() const 스레드가 종료되었는지 여부를 반환한다.
성공적으로 완료된 경우 true를 반환
bool isInterruptionRequested() const 스레드 중단 요청이 있었는지 여부를 반환한다.
requestInterruption() 함수가 호출된 경우 true를 반환
bool isRunning() const 스레드가 현재 실행 중인지 여부를 반환한다.
실행 중이면 true
int loopLevel() const 현재 스레드의 이벤트 루프 중첩 레벨을 반환한다.
이벤트 루프가 중첩된 수준을 나타낸다.
QThread::Priority priority() const 스레드의 우선순의를 반환한다.
우선순의눈 QThread::Priority 열거형에 의해 정의된다.
void requestInterruption() 스레드에 중단을 요청한다. 스레드가 주기적으로 isInterruptionRequested()를 체크하여 중단 요청을 확인하도록 해야 한다.
void setEventDispatcher(QAbstractEventDispatcher *eventDispatcher) 스레드의 이벤트 디스패처를 설정한다.
void setPriority(QThread::Priority priority) 스레드의 우선순의를 설정한다.
QThread::Priority 열거형에 의해 정의된다.
void setStackSize(uint stackSize) 스레드의 스택 크기를 설정한다.
스레드가 사용할 스택 메모리의 크기를 지정한다.
uint stackSize() const 스레드의 스택 크기를 반환한다.
bool wait(QDeadlineTimer deadline = QDeadlineTimer(QDeadlineTimer::Forever)) 지정된 QDeadlineTimer까지 스레드가 종료될 때까지 대기한다.
기본값으로는 무한정 대기
bool wait(unsigned long time) 지정된 시간(밀리초) 동안 스레드가 종료될 때까지 대기한다. 지정된 시간이 지나면 false, 종료되면 true를 반환한다.

 

enum QThread::Priority

 

예제 코드

////////[mythread.cpp]/////////

#include "mythread.h"

MyThread::MyThread(QObject *parent) : QThread(parent) {

}

void MyThread::run() {
    qDebug() << "쓰레드 시작";
    while(!isInterruptionRequested()){
        QThread::sleep(1);
        qDebug() << "쓰레드가 작동중입니다.";
    }
    qDebug() << "쓰레드가 종료 중입니다.";
}


////////[main.cpp]///////////
#include <QCoreApplication>

#include <QDebug>
#include <QDeadlineTimer>
#include <QEventLoop>

#include "mythread.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    MyThread thread;

    QObject::connect(&thread, &QThread::finished, [](){
        qDebug() << "쓰레드가 종료되었습니다.";
    });

    // Start Thread
    thread.start();
    qDebug() << "쓰레드가 작동중입니다." << thread.isRunning();

    // Set Thread Priority
    thread.setPriority(QThread::HighPriority);
    qDebug() << "쓰레드 우선 순위 : " << thread.priority();

    // Set Stack Szie
    thread.setStackSize(1024 * 1024); // 1 MB
    qDebug() << "쓰레드 스택 사이즈 : " << thread.stackSize();

    // Request interruption
    QThread::sleep(3); // Let the thread run for a while
    thread.requestInterruption();
    qDebug() << "중단 요청 : " << thread.isInterruptionRequested();

    // Wait for the thread to finish
    if (thread.wait(QDeadlineTimer(QDeadlineTimer::Forever))) {
        qDebug() << "스레드가 데드라인에 의한 종료";
    } else {
        qDebug() << "스레드가 데드라인까지 종료되지 못함";
    }

    qDebug() << "쓰레드가 종료된 상태 :" << thread.isFinished();

    return a.exec();
}

 


Public Slots

반환형 메서드 설명
void exit() 스레드의 실행을 종료하고, run() 메서드가 종료된다.
void quit() 스레드의 이벤트 루프를 종료한다. QThread를 사용하는 경우 run 메서드 안에서 이벤트 루프가 실행될 때, quit()을 호출하면 루프가 종료된다.
종료 후에는 exec()가 호출된다.
void start() 스레드를 시작한다. 선택적으로 priority를 지정하여 스레드의 우선순위를 설정한다.
void terminate() 스레드를 강제로 종료한다. 스레드가 terminate() 슬롯을 호출하면, 스레드는 즉시 종료되고, 현재 실행 중인 run() 메서드가 중단된다.

 

exit()와 quit()의 차이

  • quit()
    • 이벤트 루프가 실행 중인 경우, 현재 처리 중인 이벤트를 모두 처리한 후 이벤트 루프를 종료한다.
    • 종료 후에는 exec() 호출이 반환된다.
    • 일반적으로 이벤트 루프를 정상적으로 종료하고 싶을 때 사용된다.
  • exit()
    • 이벤트 루프가 종료되면 exec()가 반환되고, 이 반환 값은 returnCode가 된다.
    • quit()와 비슷하게 이벤트 루프를 종료하지만, 종료 시 특정 반환 값을 설정할 수 있다.
    • 기본 반환 값은 0이며, 이는 일반적으로 성공을 의미한다.

 


Signals

반환형 메서드 설명 용도
void finished() 스레드가 실행을 마치고 종료되었을 때 발생하는 시그널이다.
스레드의 run() 메서드가 완료되거나 스레드가 exit(), quit() 호출로 종료되면 이 시그널이 방출된다.
스레드가 완료된 후에 후처리를 수행하거나, 스레드 종료를 기다리는 다른 작업을 수행하는 데 사용된다.
void  started() 스레드가 시작됐을 때 발생하는 시그널이다. start() 메서드가 호출되어 스레드의 run() 메서드가 실행되기 시작할 때 이 시그널이 방출된다. 스레드가 실행을 시작할 때, 초기화 작업이나 로그 기록을 할 때 사용된다. 스레드가 실행 중임을 알리는 데 유용하다.
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    MyThread *thread = new MyThread();

    QObject::connect(thread, &QThread::started, []() {
        qDebug() << "Thread has started";
    });

    QObject::connect(thread, &QThread::finished, []() {
        qDebug() << "Thread has finished";
    });

    thread->start();
    thread->wait(); // Wait for the thread to finish

    delete thread;
    return a.exec();
}


Static Public Members

static public 멤버들은 스레드 관련 작업을 수행하거나 정보를 얻는데 사용된다.

이 함수들은 특정 QThread 객체의 멤버가 아닌 QThread 클래스 자체의 멤버로 사용된다.

메서드 설명 예시
QThread *create 새 스레드를 생성한다. QThread::create( [] () {
/* 작업 */
})->start();
QThread *currentThread() 현재 실행 중인 스레드에 대한 QThread 객체 포인터를 반환한다.
이 함수를 통해 현재 스레드의 정보를 얻을 수 있다.
QThread *current = QThread::currentThread();
Qt::HANDLE currentThreadId() 현재 실행 중인 스레드의 ID를 반환한다. Qt::HANDLE threadId
= QThread::currentThreadId();
int idealThreadCount() 시스템에서 이상적인 스레드 수를 반환 int threadCount
= QThread::idealThreadCount();
void msleep(unsigned long msecs) 현재 스레드를 지정된 밀리초 동안 정지 QThread::msleep(500);
void sleep(unsigned long secs) 현재 스레드를 지정된 초 동안 중지 QThread::sleep(2);
void sleep(std::chrono::nanoseconds nsecs) 현재 스레드를 지정된 나노초 동안 중지 QThread::sleep(std::chrono::nanoseconds(1000000));
void sleep(unsigned long usecs) 현재 스레드를 지정된 마이크로초 동안 중지 QThread::usleep(100);
void yieldCurrentThread() 현재 실행 중인 스레드가 남은 실행 시간을 다른 스레드에게 양보한다.
이는 스레드 스케줄러에게 현재 스레드의 실행을 중단하고 다른 스레드를 실행시키도록 지시한다.
QThread::yieldCurrentThread();

 


 

Protected Functions

int exec()

  • 기능 : exec() 함수는 스레드의 이벤트 루프를 실행한다. 스레드가 이벤트 루프를 실행하는 동안, 스레드는 run() 메서드가 호출되기 전까지 블록된다. 이 함수는 주로 스레드 내에서 이벤트 기반 작업을 수행할 때 사용된다.
  • 용도 : QThread를 사용하는 경우, exec()를 호출하면 스레드는 이벤트 루프를 시작하고, 이 루프가 종료될 때까지 계속 실행된다 주로 GUI 스레드나 비동기 이벤트 처리가 필요한 경우에 사용된다.
  • 리턴값 : 이벤트 루프가 종료되면, exec()는 QEventLoop::exec()와 동일한 방식으로 종료 상태 코드를 반환한다.
void MyThread::run() {
    qDebug() << "Thread started";
    exec();  // Start the event loop
    qDebug() << "Thread finished";
}

예제에서 exec()는 스레드가 이벤트 루프를 시작하도록 하고, 스레드는 이벤트 루프가 종료될 때까지 실행된다.

exec() 호출 이후에 스레드는 run() 메서드를 계속 실행한다.

 

virtual void run()

  • 기능 : run() 함수는 QThread를 상속받아 스레드에서 실행할 코드를 정의하는 가상 함수이다. 이 함수는 스레드가 시작될 때 호출된다.
  • 용도 : 스레드에서 실행할 작업을 이 함수에 정의한다. 기본 run() 구현은 아무 작업도 수행하지 않지만, QThread를 상속받은 클래스에서 이 메서드를 재정의하여 스레드의 실제 작업을 정의한다.
class MyThread : public QThread
{
    Q_OBJECT
protected:
    void run() override {
        qDebug() << "Thread started";
        QThread::sleep(2);  // Simulate some work
        qDebug() << "Thread finished";
    }
};

예제에서 run() 메서드는 스레드가 실행될 때 호출다.

스레드는 run() 메서드 내의 코드를 실행하고, 작업이 완료되면 스레드는 종료된다.


 

다음 시간에는 여러 클래스들을 QThread로 효율적인 작업을 하는 코드를 만들어보자

내일은 외근이 있어서 수요일쯤 해야겠다~