2012-12-19 12 views
11

Mam następujący kod:Dlaczego używając QMetaObject :: invokeMethod podczas wykonywania metody z nici

class A : public QObject 
{ 
    Q_OBJECT 
public: 
    A() : QObject() 
    { 
     moveToThread(&t); 
     t.start(); 
    } 
    ~A() 
    { 
     t.quit(); 
     t.wait(); 
    } 

    void doSomething() 
    { 
     QMetaObject::invokeMethod(this,"doSomethingSlot"); 
    } 
public slots: 
    void doSomethingSlot() 
    { 
     //do something 
     emit ready(); 
    } 
signals: 
    void ready(); 
private: 
    QThread t; 
} 

pytanie dlaczego z doSomething należy zadzwonić przez QMetaObject::invokeMethod. Wiem, że jest coś z typem połączenia. Czy ktoś może wyjaśnić, co kryje się pod maską?

+1

ecatmur dał wam doskonałą odpowiedź. Masz inny problem, ponieważ wątek jako członek obiektu przeniesiony do tego wątku jest bardzo złym pomysłem, podczas destrukcji (przy użyciu deleteLater) możesz mieć dziwne problemy. –

+0

Aby uzyskać pełne wyjaśnienie, przeczytaj [ten dokument] (http://doc.qt.digia.com/4.2/threads.html#per-thread-event-loop) –

+0

@MarekR: jakie problemy? Dostałem to rozwiązanie z http://stackoverflow.com/questions/13878745/correct-way-of-threading-in-qt – krzych

Odpowiedz

23

Jak Nie podano Qt::ConnectionType metoda zostanie wywołana jako Qt::AutoConnection, co oznacza, że ​​będzie ona wywoływana synchronicznie (jak normalny wywołania funkcji), jeśli nić powinowactwo obiektu jest do bieżącego wątku i asynchronicznie Inaczej. "Asynchronicznie" oznacza, że ​​QEvent jest konstruowany i wysyłany do kolejki komunikatów, i będzie przetwarzany, gdy osiągnie go pętla zdarzeń.

Powodem użycia QMetaObject::invokeMethod, jeśli obiekt odbiorcy może znajdować się w innym wątku, jest to, że próba wywołania gniazda bezpośrednio na obiekcie w innym wątku może prowadzić do uszkodzenia lub pogorszenia, jeśli dostęp do danych nie jest wątk bezpieczny.

+0

Masz na myśli to, że jeśli użyję A.doSomething() z innego wątku, może to doprowadzić do uszkodzenia? Dlaczego tak? Czy mógłbyś opisać również mechanizm? – krzych

+1

@krzych na przykład, jeśli czytasz z QStringa w tym samym czasie, gdy inny wątek go modyfikuje, to może wydawać się, że jest niespójny, co prowadzi do pośredniego nieważnego wskaźnika. – ecatmur

18

Lubię ten trick:

void A:doSomethingSlot() 
{ 
    if (thread()!=QThread::currentThread()) { 
     QMetaObject::invokeMethod(this,"doSomethingSlot", Qt::QueuedConnection); 
     return; 
    } 
    // this is done always in same thread 
    ... 
    emit ready(); 
} 
Powiązane problemy