2012-09-26 2 views
2

내 개체 (콜백)에서 SLOT 메서드를 실행하는 불투명 모듈에 개체 인스턴스를 전달하고 있습니다. 호출 모듈이 다른 스레드에 있습니다. 내 메인 스레드에서 메서드를 실행해야합니다. 신호 및 슬롯을 사용하여이 작업을 수행 할 수 있다고 생각했지만 신호 처리 된 메서드는 여전히 호출자 스레드에서 실행 중입니다. moveToThread()가있는 호출자 스레드로 객체를 옮겨야한다고 생각하지 않습니다 - 응용 프로그램의 기본 스레드에 신호를 보내는 메커니즘이 아닌가요?주 스레드에서 콜백을 실행하는 방법

MyClass::MyClass(...) 
{ 
    OtherClass::getInstance()->setCallback(this); 
    connect(this, SIGNAL(mySignalToMainThread()), this, SLOT(doThisOnMainThread())); 
} 

// Public slot, called by OtherClass on its own thread. 
void MyClass::someCallback() 
{ 
    emit mySignalToMainThread(); 
} 

void MyClass::doThisOnMainThread() 
{ 
    // AHHH! I am still on callers thread. 
} 
+0

귀하의 예를 몇 가지 중요한 정보를 벗어났습니다 : MyClass의 인스턴스는 어떤 스레드에 속해 있습니까? 슬롯을 활성화하는 데는 두 가지 가능성이 있습니다. 슬롯은 수신 객체가 속한 스레드에서 활성화되거나 (기본 동작) 신호가 방출 된 스레드에서 활성화됩니다 (Qt :: Directconnection). 그래서 MyClass의 인스턴스가 메인 쓰레드에 속하면 "그냥 작동"해야합니다. 주 스레드에 속하지 않으면이 스레드를 주 스레드로 이동할 수 있습니다. – rohanpm

답변

0

는 처음에는 그 이외의 스레드 컨텍스트에서 신호의 방출하는 MyClass에 상주 문제가 될 수 있다고 생각했다. 그러나, Qt thread documentation states : 신호 방출 스레드 안전하기 때문에

은 ... 안전하게 당신의 QThread :: 실행() 구현에서 신호를 방출 할 수있다.

그 아이디어를 거의 잊어 버릴 수 있습니다. 그리고, 당신이 Qt::AutoConnection, for which the documentation states 사용하고 : 신호가 수신 객체가 아닌 다른 스레드에서 방출되는 경우

은, 신호는 Qt는 :: QueuedConnection으로 행동, 대기. 그렇지 않으면 슬롯이 직접 호출되어 Qt :: DirectConnection으로 작동합니다. 연결 유형은 신호가 방출 될 때 결정됩니다.

특히 중요한 마지막 비트. 이 코드를 작성하는 경우 :

void MyClass::someCallback() 
{ 
    Q_ASSERT(QThread::currentThread() != this->thread()); 
    emit mySignalToMainThread(); 
} 

void MyClass::doThisOnMainThread() 
{ 
    Q_ASSERT(QThread::currentThread() == this->thread()); 
} 

나는 어설 션 실패를 기대하지는 않지만 사용자는이를 제안합니다. Qt 문서가 잘못되었거나 언급 한 것보다 더 많은 문제가 있다고 결론을 내려야합니다.

0

나를 위해 일하고있다. 어쩌면 당신의 구현을 아래에있는 것과 비교해 볼 수 있습니다.

my_class.h

class MyClass : public QObject { 
    Q_OBJECT 

public: 
    explicit MyClass(QObject *parent = 0); 

signals: 
    void mySignalToMainThread(); 

public slots: 
    void someCallback(); 
    void doThisOnMainThread(); 
}; 

MyClass::MyClass(QObject *parent) : 
    QObject(parent) { 
    std::cout << Q_FUNC_INFO << QThread::currentThreadId() << std::endl; 
    OtherClass::getInstance().setCallback(this); 
    connect(this, SIGNAL(mySignalToMainThread()), SLOT(doThisOnMainThread())); 
} 

void MyClass::someCallback() { 
    std::cout << Q_FUNC_INFO << QThread::currentThreadId() << std::endl; 
    emit mySignalToMainThread(); 
} 

void MyClass::doThisOnMainThread() { 
    std::cout << Q_FUNC_INFO << QThread::currentThreadId() << std::endl; 
} 

other_class.h my_class.cpp : 나는 누락 된 사항에 추측, 가깝게 내가 할 수와 같은 규칙을 따르도록 시도

class OtherClass : public QObject { 
    Q_OBJECT 

public: 
    static OtherClass& getInstance(); 
    void setCallback(MyClass *cb); 

public slots: 
    void doCallback(); 

private: 
    explicit OtherClass(QObject *parent = 0); 

    MyClass *cb_; 
}; 
012 3,516,

other_class.cpp

OtherClass::OtherClass(QObject *parent) : QObject(parent) { 
    std::cout << Q_FUNC_INFO << QThread::currentThreadId() << std::endl; 
} 

OtherClass& OtherClass::getInstance() { 
    std::cout << Q_FUNC_INFO << QThread::currentThreadId() << std::endl; 
    static OtherClass singleton; 
    return singleton; 
} 

void OtherClass::doCallback() { 
    std::cout << Q_FUNC_INFO << QThread::currentThreadId() << std::endl; 
    cb_->someCallback(); 
} 

void OtherClass::setCallback(MyClass *cb) { 
    std::cout << Q_FUNC_INFO << QThread::currentThreadId() << std::endl; 
    cb_ = cb; 
} 

주.CPP

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

    MyClass c; 

    QThread other; 
    OtherClass::getInstance().moveToThread(&other); 
    other.connect(&other, SIGNAL(started()), 
       &OtherClass::getInstance(), SLOT(doCallback())); 
    other.start(); 

    QMainWindow w; 
    w.show(); 

    return app.exec(); 
} 

샘플 출력 :

__thiscall MyClass::MyClass(class QObject *)00001108 
class OtherClass &__cdecl OtherClass::getInstance(void)00001108 
__thiscall OtherClass::OtherClass(class QObject *)00001108 
void __thiscall OtherClass::setCallback(class MyClass *)00001108 
class OtherClass &__cdecl OtherClass::getInstance(void)00001108 
class OtherClass &__cdecl OtherClass::getInstance(void)00001108 
void __thiscall OtherClass::doCallback(void)000015AC 
void __thiscall MyClass::someCallback(void)000015AC 
void __thiscall MyClass::doThisOnMainThread(void)00001108 
관련 문제