수색…


비고

여기여기 공식 문서에서 이미 언급 한 몇 가지 참고 사항 :

  • 객체에 부모가있는 경우 부모와 동일한 스레드에 있어야합니다. 즉, 새 스레드로 이동할 수 없으며 부모와 객체가 다른 스레드에있을 경우 부모를 객체로 설정할 수 없습니다.
  • 오브젝트가 새로운 thread로 이동하면, 그 모든 자식도 새로운 thread로 이동됩니다.
  • 객체를 새 스레드에만 푸시 할 수 있습니다. 새 스레드로 끌어 올 수 없습니다. 즉, 객체가 현재 살고있는 스레드에서만 moveToThread 를 호출 할 수 있습니다.

QThread의 기본 사용법

QThread 는 플랫폼 스레드에 대한 핸들입니다. 스레드의 수명을 모니터링하고 스레드가 작업을 완료하도록 요청하여 스레드를 관리 할 수 ​​있습니다.

대부분의 경우 클래스에서 상속하는 것은 권장되지 않습니다. 기본 run 메소드는 클래스에있는 오브젝트에 이벤트를 전달할 수있는 이벤트 루프를 시작합니다. 크로스 스레드 신호 슬롯 연결은 QMetaCallEvent 를 대상 객체로 전달하여 구현됩니다.

QObject 인스턴스는 스레드로 이동하여 타이머 이벤트 나 슬롯 / 메소드 호출과 같은 이벤트를 처리합니다.

스레드에서 작업을 수행하려면 먼저 QObject 에서 파생 된 고유 한 작업자 클래스를 만듭니다. 그런 다음 스레드로 이동하십시오. 객체는 QMetaObject::invokeMethod() 사용하여 자신의 코드를 자동으로 실행할 수 있습니다.

#include <QObject>

class MyWorker : public QObject
{
    Q_OBJECT
public:
    Q_SLOT void doWork() {
        qDebug() << "doWork()" << QThread::currentThread();
        // and do some long operation here
    }
    MyWorker(QObject * parent = nullptr) : QObject{parent} {}
};

class MyController : public QObject
{
    Q_OBJECT
    Worker worker;
    QThread workerThread;
public:
    MyController()  {
        worker.moveToThread(&workerThread);
        // provide meaningful debug output
        workerThread.setObjectName("workerThread");
        workerThread.start();
        // the thread starts the event loop and blocks waiting for events
    }
    ~MyController()  {
        workerThread.quit();
        workerThread.wait();
    }
    void operate() {
        // Qt::QueuedConnection ensures that the slot is invoked in its own thread
        QMetaObject::invokeMethod(&worker, "doWork", Qt::QueuedConnection);
    }
};

작업자가 일시적이어야하며 작업이 완료되는 동안 만 존재해야하는 경우 QtConcurrent::run 통해 스레드 풀에서 실행을 위해 펑터 또는 스레드 안전 메소드를 제출하는 것이 가장 좋습니다.

Qt 동시 실행

뮤텍스 또는 세마포어와 같은 QThreads 및 저수준 프리미티브를 관리하는 것이 너무 복잡하다면 Qt 동시 네임 스페이스가 원하는 것입니다. 여기에는 더 높은 수준의 스레드 관리를 허용하는 클래스가 포함됩니다.

Concurrent Run을 살펴 보겠습니다. QtConcurrent::run() 은 새 스레드에서 함수를 실행할 수있게합니다. 언제 그것을 사용하고 싶습니까? 긴 작업이 있고 수동으로 스레드를 만들지 않으려는 경우

이제 코드 :

#include <qtconcurrentrun.h>

void longOperationFunction(string parameter)
{
    // we are already in another thread
    // long stuff here
} 

void mainThreadFunction()
{
    QFuture<void> f = run(longOperationFunction, "argToPass");
    f.waitForFinished();
}

그래서 간단합니다 : 다른 스레드에서 다른 함수를 실행해야 할 때 QtConcurrent::run 호출하고 함수와 매개 변수를 전달하면됩니다.

QFuture 는 우리의 비동기 계산 결과를 보여줍니다. QtConcurrent::run 경우 함수 실행을 취소 할 수 없습니다.

다른 스레드에서 슬롯 호출

Qt 이벤트 루프를 사용하여 작업을 수행하고 비 Qt 사용자가 해당 이벤트 루프와 상호 작용해야 할 때 다른 스레드의 일반 호출을 처리하는 슬롯을 작성하면 다른 사용자의 작업을 단순화 할 수 있습니다.

main.cpp :

#include "OperationExecutioner.h"
#include <QCoreApplication>
#include <QThread>

int main(int argc, char** argv)
{
    QCoreApplication app(argc, argv);

    QThread thrd;
    thrd.setObjectName("thrd");
    thrd.start();
    while(!thrd.isRunning())
        QThread::msleep(10);

    OperationExecutioner* oe = new OperationExecutioner;
    oe->moveToThread(&thrd);
    oe->doIt1(123,'A');
    oe->deleteLater();
    thrd.quit();
    while(!thrd.isFinished())
        QThread::msleep(10);

    return 0;
}

OperationExecutioner.h :

#ifndef OPERATION_EXECUTIONER_H
#define OPERATION_EXECUTIONER_H

#include <QObject>

class OperationExecutioner : public QObject
{
    Q_OBJECT
public slots:
    void doIt1(int argi, char argc);
};

#endif  // OPERATION_EXECUTIONER_H

OperationExecutioner.cpp :

#include "OperationExecutioner.h"
#include <QMetaObject>
#include <QThread>
#include <QDebug>

void OperationExecutioner::doIt1(int argi, char argc)
{
    if (QThread::currentThread() != thread()) {
        qInfo() << "Called from thread" << QThread::currentThread();
        QMetaObject::invokeMethod(this, "doIt1", Qt::QueuedConnection,
                                  Q_ARG(int,argi), Q_ARG(char,argc));
        return;
    }

    qInfo() << "Called from thread" << QThread::currentThread()
            << "with args" << argi << argc;
}

OperationExecutioner.pro :

HEADERS += OperationExecutioner.h
SOURCES += main.cpp OperationExecutioner.cpp
QT -= gui


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow