문제

내 응용 프로그램에는 기본 스레드와 작업자 스레드가 있습니다 (QThread).
메인 스레드에서 작업자 스레드의 메소드를 호출하고 스레드의 컨텍스트에서 실행하도록합니다.

사용해 보았습니다 QMetaObject::invokeMethod 그리고 그것을 줘 QueuedConnection 옵션이지만 작동하지 않습니다.
또한 메인 스레드 (작업자 스레드 슬롯에 연결되어 있음)에서 신호를 방출하려고 시도했지만 실패했습니다.

다음은 내가 시도한 대략적인 스 니펫입니다.

class Worker : public QThread
{
    Q_OBJECT

public:
    Worker() { }

    void run() 
    { 
        qDebug() << "new thread id " << QThread::currentThreadId(); 
        exec(); 
    }

public slots:
    void doWork()
    {
        qDebug() << "executing thread id - " << QThread::currentThreadId();
    }
};

QMetaObject 방식 사용 :

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

    qDebug() << "main thread id - " << QThread::currentThreadId();

    Worker worker;
    worker.start();

    QMetaObject::invokeMethod(&worker, "doWork", Qt::QueuedConnection);

    return a.exec();
}

신호 방법 사용 :

class Dummy : public QObject
{
    Q_OBJECT

public:
    Dummy() { }

public slots:
    void askWork() { emit work(); }

signals:
    void work();
};

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

    qDebug() << "main thread id - " << QThread::currentThreadId();

    Worker worker;
    worker.start();

    Dummy dummy;
    QObject::connect(&dummy, SIGNAL(work()), &worker, SLOT(doWork()), Qt::QueuedConnection);

    QTimer::singleShot(1000, &dummy, SLOT(askWork()));

    return a.exec();
}

두 가지 방법 모두 메인 스레드 ID가 인쇄됩니다. QThread doWork.

또한 간단한 생산자 소비자를 구현할 생각이지만 이것이 효과가 있다면 왜 이런 식으로 그렇게하지 않는 이유가 있습니까?

도움이 되었습니까?

해결책

문제는 수신기 (Qthread)가 기본 스레드에서 '살아 가기'하므로 기본 스레드의 이벤트 루프는 슬롯을 실행하는 것입니다.

QT의 문서에서 :

대기열 연결을 사용하면 컨트롤이 객체가 속한 스레드의 이벤트 루프로 돌아올 때 슬롯이 호출됩니다. 슬롯은 수신기 객체가있는 스레드에서 실행됩니다.

그래서 지금까지 찾은 솔루션은 스레드 런 () 내부에 객체를 만들고 대신 슬롯을 사용하는 것이 었습니다. 이렇게하면 수신기의 소유자가 스레드이고 슬롯이 스레드 컨텍스트에서 호출됩니다.

다른 팁

이 예제는 작업자 클래스를 분할하여 원하는대로 작동하도록하는 방법을 보여줍니다. 또한 슬롯에 연결할 수 있도록 작업자 인스턴스에 대한 참조 또는 포인터를 사용할 수 있도록해야합니다.

class Worker : public QObject
{
    Q_OBJECT

public:
    Worker() { }

public slots:
    void doWork()
    {
        qDebug() << "executing thread id - " << QThread::currentThreadId();
    }
};

class WorkerThread : public QThread
{
    Q_OBJECT

public:
    void run()
    {
        qDebug() << "new thread id " << QThread::currentThreadId(); 
        Worker worker;
        exec();
    }
};

간단한 프로듀서 소비자 예를 위해 Bradley T. Hughes의 블로그 항목을 살펴보십시오. 두통없이 밟는 것.

작업자는 기본 스레드에서 생성되므로 이벤트는 기본 스레드에서 처리됩니다. 작업자를 자신의 스레드로 옮겨야합니다.

Worker worker;
worker.moveToThread(&worker);
worker.start();

이제 QT는 알고 있습니다 worker 새로운 스레드에 살고 있으며 해당 이벤트 루프에서 이벤트를 줄입니다.

기능을 호출하거나 신호를 보내기 전에 작업자 스레드가 완료되는 것처럼 보입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top