Nice programing

Qt에서 크로스 스레드 신호를 방출하는 방법은 무엇입니까?

nicepro 2020. 12. 12. 12:29
반응형

Qt에서 크로스 스레드 신호를 방출하는 방법은 무엇입니까?


Qt 문서에 따르면 신호와 슬롯은 direct, queuedauto.

또한 슬롯을 소유 한 객체가 시그널을 소유 한 객체와 다른 스레드에 '살아있다'면 이러한 시그널을 방출하는 것은 메시지를 게시하는 것과 같을 것입니다. 시그널 방출은 즉시 반환되고 슬롯 메소드는 타겟 스레드의 이벤트 루프에서 호출됩니다.

불행히도 문서에는 '생명'이 의미하는 것으로 명시되어 있지 않으며 사용 가능한 예가 없습니다. 다음 코드를 시도했습니다.

main.h:

class CThread1 : public QThread
{
Q_OBJECT
public:
    void run( void )
    {
        msleep( 200 );
        std::cout << "thread 1 started" << std::endl;
        MySignal();
        exec();
    }
signals:
    void MySignal( void );
};

class CThread2 : public QThread
{
Q_OBJECT
public:
    void run( void )
    {
        std::cout << "thread 2 started" << std::endl;
        exec();
    }
public slots:
    void MySlot( void )
    {
        std::cout << "slot called" << std::endl;
    }
};

main.cpp:

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    CThread1 oThread1;
    CThread2 oThread2;
    QObject::connect( & oThread1, SIGNAL( MySignal() ),
        & oThread2, SLOT( MySlot() ) );
    oThread1.start();
    oThread2.start();
    oThread1.wait();
    oThread2.wait();
    return a.exec();
}

출력은 다음과 같습니다.

thread 2 started
thread 1 started

MySlot() :(. 내가 뭘 잘못하고 있니?


코드에는 몇 가지 문제가 있습니다.

  • Evan이 말한 것처럼 emit 키워드가 없습니다.
  • 모든 개체는 주 스레드에 있고 실행 메서드의 코드 만 다른 스레드에 있습니다. 즉, MySlot 슬롯이 주 스레드에서 호출되고 이것이 원하는 것인지 잘 모르겠습니다.
  • 메인 이벤트 루프가 시작되지 않았으므로 슬롯이 호출되지 않습니다. wait ()에 대한 두 번의 호출은 매우 오랜 시간이 지난 후에 만 ​​시간 초과됩니다 (그리고 그 전에 응용 프로그램을 종료 할 수 있음). 그것은 당신이 원하는 것입니다. 어쨌든 그들은 당신의 코드에서 실제로 사용하지 않습니다.

이 코드는 대부분 작동 할 것이며 (테스트하지는 않았지만) 원하는대로 작동한다고 생각합니다.

class MyObject : public QObject
{
    Q_OBJECT
public slots:
    void MySlot( void )
    {
        std::cout << "slot called" << std::endl;
    }
};

class CThread1 : public QThread
{
    Q_OBJECT
public:
    void run( void )
    {
        std::cout << "thread 1 started" << std::endl;
        int i = 0;
        while(1)
        {
           msleep( 200 );
           i++;
           if(i==1000)
              emit MySignal();
        }
    }
signals:
    void MySignal( void );
};

class CThread2 : public QThread
{
    Q_OBJECT
public:
    void run( void )
    {
        std::cout << "thread 2 started" << std::endl;
        exec();
    }
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    CThread1 oThread1;
    CThread2 oThread2;
    MyObject myObject;
    QObject::connect( & oThread1, SIGNAL( MySignal() ),
        & myObject, SLOT( MySlot() ) );
    oThread2.start();
    myObject.moveToThread(&oThread2)
    oThread1.start();
    return a.exec();
}

이제 MyObject는 thread2에 있습니다 (moveToThread 덕분에).

MySignal은 thread1에서 전송되어야합니다 (확실하지 않다고 생각하면 메인 스레드에서 전송 될 수 있지만 실제로는 중요하지 않습니다).

No event loop is needed in thread1 since emitting a signal doesn't need an event loop. An event loop is needed in thread2 (lanched by exec()) to receive the signal.

MySlot will be called in thread2.


Do not subclass QThread for Qt 4.4+

While Aiua's answer is good, I want to point out some issues with QThread and Qt 4.6 or 4.7.

This article sums it up: http://blog.qt.io/blog/2010/06/17/youre-doing-it-wrong/

Lack of Documentation on Qt's part

Unfortunately the problem stems from a lack of updates to documentation. Prior to Qt 4.4 QThread had no default run() implementation, which meant that you had to subclass QThread in order to use it.

If you're using Qt 4.6 or 4.7 then you almost certainly should not subclass QThread.

Use moveToThread

The key to getting slots to execute in a worker thread is to use the moveToThread method as Aiua pointed out.


you should emit the signal to start your thread function like

emit operateCut(examId,examName_examTemplate[examName].studentIdRec,examName_examTemplate[examName].choiceRecA,examName_examTemplate[examName].choiceRecB,examName_examTemplate[examName].objectRecA,examName_examTemplate[examName].objectRecB);

you can add more than one argument in this signal

참고URL : https://stackoverflow.com/questions/638251/how-to-emit-cross-thread-signal-in-qt

반응형