2009-12-28 29 views
5

Próbuję uruchomić metodę na wątku GUI za pomocą QMetaObject :: invokeMethod, która zwraca wartość true. Ale jeśli używam Qt :: QueuedConnection, moja metoda nigdy nie zostanie wywołana (nawet jeśli invokeMethod zwróci true).QMetaObject :: invokeMethod zwraca true, ale metoda nigdy nie jest wywoływana

To właśnie używam:

QMetaObject::invokeMethod(this, "draw_widgets", Qt::QueuedConnection) 

ja nie otrzymuję żadnych komunikatów o błędach lub cokolwiek ... Jeśli używam Qt :: AutoConnection lub Qt :: DirectConnection który to sposób robi się nazywa , ale z tego samego wątku oczywiście. Nie z wątku GUI, który jest tym, czego potrzebuję.

draw_widgets to publiczne gniazdo typu void draw_widgets() , a moja klasa dziedziczy QObject i używa również makra Q_OBJECT.

Byłbym wdzięczny za pomoc w tej sprawie lub w jaki sposób sprawdzić, dlaczego metoda nie jest wywoływana.

Dzięki.

+0

Mam podobną sytuację : Mam klasę, która dziedziczy z QObject i używa 'Q_OBJECT'. Instancja tej klasy jest tworzona w pętli głównej. Następnie, podczas wykonywania metody tej samej klasy w pętli głównej, nazywam 'QMetaObject :: invokeMethod (this," hideListsSlot ", Qt :: QueuedConnection);', gdzie 'void hideListsSlot()' jest publicznym slotem klasa. Slot nigdy nie jest wywoływany. – Giorgio

Odpowiedz

10

"Wartość true" informuje, że wiadomość została pomyślnie umieszczona w kolejce. To nie znaczy, że kolejka wiadomości została kiedykolwiek przetworzona ...

Powiedzmy, że Twój program ma 10 wątków (wątek1-wątek10). W kolejce wiadomość z Thread7. W którym wątku będzie on umieszczany w kolejce? A kiedy będą przetwarzane elementy w tej kolejce?

Odpowiedź jest taka, że ​​każdy element QObject ma coś, co nazywa się Thread Affinity i jest to wątek, w którym zostanie uruchomione kolejkowane gniazdo. Domyślną powinowactwo do wątku, gdzie obiekt został utworzony (ale można go zmienić z QObject::moveToThread().)

Jeśli chcesz stać w kolejce coś do wątku GUI, a następnie obiekt wskazany przez wskaźnik this powinien mieć GUI wątku powinowactwo. Możesz to sprawdzić za pomocą metody QObject::thread().

Ale w każdym przypadku, bez względu na to, do jakiego wątku w kolejce ... musisz mieć jakąś pompę komunikatów uruchomioną w tym wątku. Spójrz na przykład na QThread::exec(). Jeśli twoje powinowactwo wątku do GUI, prawdopodobnie jest to już przypadek, ponieważ uruchamiasz aplikację.

(Jak sidenote, bezpośrednie połączenia do QMetaObject::invokeMethod są zazwyczaj niepotrzebne. Można utworzyć sygnał i przywiązać go do gniazda, a następnie emituje sygnał w miejsce invoke.)

+0

Bardzo dziękuję za odpowiedź. Nie wiedziałem o powinowactwie wątku. Zmiana powinowactwa obiektu do wątku GUI rozwiązała problem. –

+0

@HostileFork naprzeciwko sidenote, jeśli masz zbyt wiele gniazd, zostaną utworzone sygnały tak samo jak gniazda, więc w tym przypadku wystarczy użyć 'QMetaObject :: invokeMethod (this," slot 1 ... n ", Qt :: QueuedConnection) '. –

+0

@HostileFork naprzeciwko sidenote kontynuuj, wywołanie 'invokeMethod' powinno być zaznaczone wewnątrz warunku check' if (QThread :: currentThread()! = Thread()) '. w ten sposób klienci mogą dzwonić do automatów. –

Powiązane problemy