2014-07-17 4 views
0

파생 된 QThread 클래스를 작성하여 응용 프로그램을 스크립팅 가능하게 만들었습니다.이 클래스에서는 명령 줄을 통해 해당 함수에 액세스하기 위해 다중 QObject 클래스를 추가합니다. 실행() 호출 후 스레드 응용 프로그램에서 QtScript에서 호출 된 Qt 슬롯

void commandLine::addObject(QObject *obj, QString name) 
{ 
    QScriptValue sv = m_scriptEngine.newQObject(obj); 
    m_scriptEngine.globalObject().setProperty(name, sv); 

    qObjectMap.insert(std::pair<QString, QObject *>(name, obj)); 
} 

이 클래스는 모든 명령 행 입력 평가 m_scriptEngine을 사용하여 무한 루프에 입력합니다.

simuCLI cli; 
simuCore core; 
cli.addObject(&core, "core"); 
simuUI ui; 
connect(&ui, SIGNAL(start()), &core, SLOT(start())); 

을하지만 내 GUI에서 내 스크립트에서() 시작을 호출 할 때, 결과의 differents은

내 응용 프로그램 아키텍처가 같다 : 내 (간체) 주에서

내가 할 다음

코어 -> 머신 (StateMachine) -> 시스템 -> 통신

UI에서 시작하는 것이 좋습니다.

명령 줄에서 시작하여 코드를 실행하십시오. 그러나 QStateMachine을 시작하지 마십시오. 신호를 방출하지만 결코 수신하지 않습니다.

CommunicationMachine에 수신 된 신호를 방출하여 Machine으로 명령을 보냅니다. 그것은 내 UI에서 core :: start()를 호출하면 작동합니다 내 명령 줄 신호를 사용하여 core :: start()를 호출하면 신호가 나오지만 결코 수신되지 않습니다.

void WL::WL() 
{ 
    std::cout << "wl cst" << std::endl; 
    mLectMotStateMachine.setInitialState(sNoCard); 
    mLectMotStateMachine.start(); 
} 
void WL::enterNoCard() 
{ 
    std::cout << "no card" << std::endl; 
} 

OUPUT : UI에서

시작() :

wl cst 
no card 

시작() 명령 줄에서 :

wl cst 

당신이 볼 수 있듯이, 상태 머신 절대 진입하지 않는 것처럼 첫 번째 주에 입력하지 마십시오.

그래서 제 질문은 다음과 같습니다

1 - 느릅 나무 스레드에서 시작() 나는 명령 라인에서 그것을 호출하는 경우를 실행?

2 - 어떻게 신호를 디버깅 할 수 있습니까? (best answer I've found)

3 - 내가 실행 오전하는 스레드에서 알 수있는 방법 - 실행

4 시간 't'에서 모든 신호 연결을 볼 수있는 방법이 있습니까?

5 - 내 코드가 명령 줄을 사용할 때만 작동하지 않는 이유가 있습니까?

+0

는, 특히 연결 시작하여 커넥트를 확인()을 활성화해야합니다. 추가 도움이 필요하면 우편 번호를 보내주십시오. –

+0

나는 나의 포스트를 더 명백하게 편집했다. – MokaT

답변

1

다른 스레드에있는 오브젝트에서 스레드 안전하지 않은 메소드를 직접 호출하면 오류가 발생합니다. 나는 simuCore 객체가 QThread이고 스레드에 다른 객체들을 만들어 낸다고 생각합니다. 이러한 객체는 다른 스레드에서 직접 액세스 할 수 없으면 스레드로부터 안전하게 액세스 할 수 있습니다 (실제로는 그렇지 않습니다).

답변은 다음과 같습니다

  1. 당신은 그것을 확인할 수 있습니다. start() 방법 내에서 추가 : 당신은 그것을 또한 메인 쓰레드 또는 GUI 스레드로 알려진 qApp->thread()와 같은 스레드가 있다고 볼 수

    qDebug() << QThread::currentThread(); 
    

    .

  2. 신호 디버깅의 의미를 모르겠습니다. 신호 슬롯 메커니즘은 분명히 작동하므로 디버깅 할 부분은 무엇입니까?

  3. 왜 필요한가요? 당신은 연결을 만들고있는 중입니다. 따라서 연결을 설정하고 끊는 지점에서 디버그 출력을 확실히 추가 할 수 있습니다. 마술은 없다.

  4. QThread::currentThread().

  5. 당신이있어 때문에 : 개체가있는 스레드가 아닌 다른 스레드에서 스레드 안전하지 않은 방법을 호출

    • .

    • QThread에서 파생하지 말아야 할 때.

    당신은, 대신, 단순히 전용 일반 QThread (NO 서브 클래스)에 스크립트 엔진 객체를 이동하고 명령 줄을 평가하기 위해 스레드 안전 메소드 호출을 사용해야합니다. 신호 슬롯 연결은 스레드 안전하며 QMetaObject::invokeMethod입니다. 예를 들어

:

#include <QCoreApplication> 
#include <QScriptEngine> 
#include <QThread> 

class ScriptEngine : public QScriptEngine { 
    Q_OBJECT 
    Q_SIGNAL void evaluateSignal(const QString &); 
public: 
    Q_SLOT void evaluate(const QString & str) { QScriptEngine::evaluate(str); } 
    /// A thread-safe evaluate() 
    Q_SLOT void safeEvaluate(const QString & str) { emit evaluateSignal(str); } 
    explicit ScriptEngine(QObject * parent = 0) : QScriptEngine(parent) { 
     connect(this, &ScriptEngine::evaluateSignal, this, &ScriptEngine::evaluate); 
    } 
}; 

class Thread : public QThread { 
    // A thread that's safe to destruct, like it ought to be 
    using QThread::run; // final 
public: 
    ~Thread() { quit(); wait(); } 
}; 

int main(int argc, char ** argv) { 
    QCoreApplication app(argc, argv); 
    ScriptEngine engine; 
    Thread worker; 
    engine.globalObject().setProperty("qApp", engine.newQObject(qApp)); 
    engine.moveToThread(&worker); 
    worker.start(); 

    QMetaObject::invokeMethod(&engine, "evaluate", Q_ARG(QString, "print('Hi!')")); 
    engine.safeEvaluate("print('And hello!')"); 
    engine.safeEvaluate("qApp.quit()"); 
    return app.exec(); 
} 

#include "main.moc" 
+0

와우 감사. 이것은 QThread의 실제 구현입니다. 나는 도움이 될 수있는 [this] (http://blog.qt.digia.com/blog/2010/06/17/youre-doing-it-wrong/)을 발견했습니다. – MokaT

+0

Qt Dev Andre가 [QThread class ref] (http://qt-project.org/doc/qt-4.8/qthread.html#notes)에 대한 훌륭한 예입니다. – MokaT

+0

주 :'qApp.quit()'호출은'app.exec()'와 경쟁 관계에 있습니다.'app.exec()'가 들어가기 전에 worker 스레드에서 실행될 가능성이 있습니다. 아니야. TODO 나중에 :) –