2012-03-21 23 views
22

Qt documentation stwierdza, że ​​jest możliwe, aby połączyć ze sobą dwa sygnały:Qt połączyć ze sobą za pomocą dwóch sygnałów QueuedConnection

Jest nawet możliwe, aby podłączyć sygnał bezpośrednio do innego sygnału.

Próbowałem:

connect(x, SIGNAL(S()), y, SIGNAL(func())); 

i działa jak wspomniano, ale dokumentacja Qt kontynuuje: (. Ten natychmiast emitować drugi sygnał, gdy pierwszy jest emitowany)

Czy to oznacza, że ​​QueuedConnection nie będzie działać poprawnie? Czy mogę połączyć dwa sygnały w wątkach?

Powodem, dla którego o to pytam jest to, że rozwiązałem klasę awarii aplikacji, unikając tego, ale nie jestem pewien, czy było to związane z łączeniem sygnałów.

+2

Czy próbowałeś tworzenia przypadków testowych połączeń poprzecznych gwintowane sygnał sygnał? Wydrukuj komunikat przed i po oryginalnym sygnale (w jednym wątku) oraz w gnieździe połączonym z drugim sygnałem (w drugim wątku).W drugim wątku wielokrotnie wywołuj "uśpienie" trwające sekundę lub dwie w pętli zdarzeń, aby było bardziej oczywiste, że szczelina w tym wątku jest wywoływana albo synchronicznie z pierwszym wątkiem, albo asynchronicznie w drugim wątku. – tmpearce

+0

@ tmpearce- dobra rada, spróbuję i opublikuję tutaj wynik – dashesy

+2

Czy kiedykolwiek próbowałeś? – gnovice

Odpowiedz

24

Nie powinno to być nic innego niż połączenie sygnału/gniazda. Rzućmy okiem na ukryty mechanizm sygnałów/gniazd. W każdym wątku znajduje się kolejka zdarzeń, która utrzymuje sygnały (zdarzenia), które zostały wyemitowane, ale jeszcze nie przetworzone. Tak więc, gdy wykonanie powraca do pętli zdarzeń, przetwarzana jest kolejka. Sama pętla zdarzeń nie obsługuje zdarzeń. Raczej dostarcza je do obiektów, aby mogli sobie z tym poradzić. W tym szczególnym przypadku, przypuszczam, że obiekt wyemitowałby inny sygnał, który zostałby wstawiony do kolejki. Kiedy wykonanie powraca do pętli zdarzeń, nowy sygnał jest ponownie obsługiwany przez obiekt. Oto test, który potwierdza powyższy argument.

Jeśli prowadzisz kody dołączone wyjście byłoby:

before signal() 
after signal() 
slot() called 

co oznacza zdefiniowanie typu połączenia sygnału sygnału w kolejce pomiędzy wątkami są oczekiwane w kolejce zachowanie, które odrzuca argument, który jest zawsze natychmiastowy. Jeśli zdefiniujesz to jako bezpośrednie, wyjście będzie:

before signal() 
slot() called 
after signal() 

zgodnie z oczekiwaniami. nie generuje żadnych błędów ani ostrzeżeń, a program również się nie psuje. Ten prosty przykład nie dowodzi, że działa również dla dużego i złożonego.

main.cpp:

#include <QtGui/QApplication> 
#include "dialog.h" 
#include "testssconnection.h" 

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

    TestSignalSignalConnection * t = new TestSignalSignalConnection(); 
    t->start(); 

    return a.exec(); 
} 

testssconnection.h:

#ifndef TESTSSCONNECTION_H 
#define TESTSSCONNECTION_H 

#include <QObject> 
#include <QThread> 

class TestSignalSignalConnection : public QThread 
{ 
    Q_OBJECT 
public: 
    explicit TestSignalSignalConnection(QObject *parent = 0); 

    void run(); 

signals: 
    void signal1(); 
    void signal2(); 

public slots: 
    void slot(); 
}; 

#endif // TESTSSCONNECTION_H 

testssconnection.cpp:

#include "testssconnection.h" 
#include <QtCore> 

TestSignalSignalConnection::TestSignalSignalConnection(QObject *parent) : 
    QThread(parent) 
{ 
} 

void TestSignalSignalConnection::run() 
{ 
    TestSignalSignalConnection *t = new TestSignalSignalConnection(); 

    this->connect(this,SIGNAL(signal1()),t,SIGNAL(signal2()), Qt::QueuedConnection); 
    t->connect(t,SIGNAL(signal2()), t,SLOT(slot()), Qt::DirectConnection); 

    qDebug() << "before signal()"; 
    emit signal1(); 
    qDebug() << "after signal()"; 

    exec(); 
} 

void TestSignalSignalConnection::slot() 
{ 
    qDebug() << "slot() called"; 
} 
Powiązane problemy