2013-02-24 13 views
29

Mam problem z sygnałami Qt.Sygnały Qt (QueuedConnection i DirectConnection)

Nie rozumiem, jak działa DirectConnection i QueuedConnection?

Byłbym wdzięczny, gdyby ktoś wyjaśnił, kiedy należy skorzystać z którego z nich (przykładowy kod byłby mile widziany).

+1

Zobacz http://stackoverflow.com/questions/11230080/qobject-based-class-has-a-queued-connection-toself i http://qt-project.org/doc/qt-4.8/ threads-qobject.html – user1929959

+2

Czego konkretnie nie rozumiesz? Twoje pytanie sprowadza się do tego, "jak działają sygnały i automaty" bez tego, co jest nieco obszerne i dobrze opisane w dokumentach. – Mat

+0

Hmm .. o ile rozumiem, QueuedConnection powinien być używany, gdy nadawca i odbiorca są w różnych wątkach. Na przykład mam wątek GUI (główny wątek) i nowy wątek (pThread), który ma na przykład sygnał void doSomething(); i odbiornik jest głównym wątkiem GUI. Tak więc, muszę korzystać z QueuedConnection, nieważne, jak to nazwać? (w wątku GUI lub nowym wątku, polecenie connect) Dziękuję .. – Nika

Odpowiedz

61

Nie zobaczysz dużej różnicy, chyba że pracujesz z obiektami o różnych powinowactwach do gwintów. Załóżmy, że masz QObjects A i B i oba są dołączone do różnych wątków. A ma sygnał o nazwie somethingChanged() i B ma gniazdo o nazwie handleChange().

Jeśli używasz bezpośredniego połączenia

connect(A, SIGNAL(somethingChanged()), B, SLOT(handleChange()), Qt::DirectConnection); 

przy czym sposób handleChange() będzie faktycznie działać w wątku A „s. Zasadniczo jest tak, jakby emitowanie sygnału wywoływało metodę "bezpośrednio". Jeśli B::handleChange() nie jest bezpieczny dla wątków, może to powodować niektóre (trudne do zlokalizowania) błędy. Przynajmniej tracisz zalety dodatkowego wątku.

Jeśli zmienisz metodę połączenia na Qt::QueuedConnection (lub, w tym przypadku niech Qt zdecyduje, której metody użyć), sprawy będą bardziej interesujące. Zakładając, że wątek B uruchamia pętlę zdarzeń, emitowanie sygnału spowoduje opublikowanie zdarzenia w pętli zdarzeń B. Pętla zdarzeń umieszcza w kolejce zdarzenie i ostatecznie wywołuje metodę szczeliny, gdy tylko sterowanie wróci do niej (jest to pętla zdarzeń). To sprawia, że ​​łatwo jest poradzić sobie z komunikacją pomiędzy/między wątkami w Qt (ponownie, zakładając, że twoje wątki uruchamiają własne lokalne pętle zdarzeń). Nie musisz się martwić o zamki, itp., Ponieważ pętla zdarzeń serializuje inwokacje wrzutowe.

Uwaga: Jeśli nie wiesz, jak zmienić powinowactwo wątku QObject, spójrz na QObject::moveToThread. To powinno ci na początek wystarczyć.

Edit

powinienem wyjaśnić moje otwarcie zdanie. To robi różnicę, jeśli określić w kolejce połączenie - nawet dla dwóch obiektów w tym samym wątku. Zdarzenie jest nadal publikowane w pętli zdarzeń wątku. Tak więc wywołanie metody jest nadal asynchroniczne, co oznacza, że ​​może być opóźnione w nieprzewidywalny sposób (w zależności od innych zdarzeń, które pętla może potrzebować do przetworzenia). Jeśli jednak nie określisz metody połączenia, metoda bezpośrednia jest automatycznie używana do połączeń między obiektami w tym samym wątku (przynajmniej jest to w Qt 4.8).

+0

@Jacob, więc czy nie lepiej jest bezpośrednio wywoływać handleChange() jak normalną funkcję zamiast wchodzenia w zamieszanie SIGNAL SLOT dla przypadku Direct Connection? –

+3

Cool_Coder: Zaletą wywołania metody poprzez połączenie sig/slot jest to, że nie musisz budować wiedzy o obiekcie 'B' w' A' - możesz pozwolić użytkownikowi dwóch klas określić, co powinno się stać, gdy 'somethingChanged 'jest emitowane z' A'. Czy to ma sens? –

16

oprócz Jacob Robbins odpowiedź:

stwierdzenie „Nie będzie widać wielkiej różnicy, chyba że pracujesz z obiektami mającymi różne powinowactwo nici” jest źle;

wysyłanie sygnału do bezpośredniego połączenia w obrębie tego samego wątku spowoduje natychmiastowe wykonanie tego gniazda, podobnie jak zwykłe wywołanie funkcji.

wysyłanie sygnału do oczekującego połączenia w obrębie tego samego wątku spowoduje nadpisanie połączenia w pętli zdarzeń wątków, a zatem wykonanie będzie zawsze opóźnione o .

QObject based class has a queued connection to itself

+0

Teraz całkowicie zrozumiałem sygnały i automaty, dziękuję, że o tym wspomniałem. – Nika

+0

Dobra uwaga. Zawsze pozwalam Qt wybrać metodę połączenia, chyba że mam dobry powód, aby wybrać jeden lub drugi ... więc otrzymuję bezpośrednie połączenie. kiedy obiekty znajdują się na tym samym wątku (używając 4.8). To zdecydowanie robi różnicę, jeśli wymusisz połączenie w kolejce. Poprawiłem moją odpowiedź, aby wyjaśnić. –

0

odpowiedź Jakuba jest niesamowite. Chciałbym dodać przykład porównawczy do programowania wbudowanego.

Wychodząc z osadzonego tła RTOS/ISR, pomocne było zobaczenie podobieństw w DirectConnection Qt do zachowania Zaporowego ISR i Qt's QueuedConnection do Queued Messages w RTOS pomiędzy zadaniami.

Nota boczna: Wychodząc z osadzonego tła, trudno mi nie zdefiniować zachowania w programowaniu. Nigdy nie zostawiam argumentu jako Auto, ale to tylko osobista opinia. Wolę wszystko, co trzeba wyraźnie napisać, i tak, czasami staje się to trudne!