2013-06-07 51 views
6

Chciałbym potwierdzić, co moim zdaniem jest prostym aspektem wątków roboczych w Qt.Czy w Qt blokuje się pętlę zdarzeń QThread, gdy wykonywany jest slot w obiekcie QObject będącym własnością wątku pętli zdarzeń?

Załóżmy, że tworzę QThread, którego celem jest zarządzanie czasochłonną pracą w odpowiadającym mu wątku. Ponadto przypuśćmy, że pozwolę na uruchamianie pętli zdarzeń tego wątku przez wywołanie start() na QThread. Samo działanie jest wykonywane przez funkcję składową (slot), która jest sygnalizowana przez sygnał QThread'a o numerze started().

To jest (kopiowanie z https://stackoverflow.com/a/11039216/368896):

class Task : public QObject 
{ 
Q_OBJECT 
public: 
    Task(); 
    ~Task(); 
public slots: 
    void doWork() 
    { 
     //very time-consuming code is executed here before the next line is reached... 
     emit workFinished(); // Calls workFinished() signal (after a long time) 
    } 
signals: 
    void workFinished(); 
}; 

// ... in the main thread: 
QThread *thread = new QThread(); 
Task *task = new Task(); 
task->moveToThread(thread); 
connect(thread, SIGNAL(started()), task, SLOT(doWork())); 
connect(task, SIGNAL(workFinished()), thread, SLOT(quit())); 
//automatically delete thread and task object when work is done: 
connect(thread, SIGNAL(finished()), task, SLOT(deleteLater())); 
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); 
thread->start(); 

Moje pytanie jest następujące. Rozumiem, że pętla zdarzeń wątku roboczego otrzyma sygnał z sygnału finished() w celu wywołania gniazda deleteLater() w instancji task. Ta pętla zdarzeń będzie działać wkrótce po przywróceniu funkcji doWork(), a zatem będzie gotowa i dostępna do przetworzenia wyzwalacza z sygnału finished(), który został dodany do kolejki zdarzeń wątku roboczego przez połączenie z numerem finished() na końcu. funkcji doWork().

Chciałbym potwierdzić, że w czasie całego przebiegu czasochłonne wykonywane wewnątrz doWork() (przed finished() emitowany jest przed zakończeniem funkcyjnych doWork()), że pętla zdarzenia wewnątrz gwintu roboczych jest zablokowany na Funkcja szczeliny doWork() i dlatego wątek roboczy będzie NOT reagować na wszystkie sloty wyzwalane na obiektach należących do wątku pętli zdarzeń podczas całego przebiegu czasochłonnej funkcji doWork(). (A to dlatego, wszelkie takie szczeliny będą realizowane dopiero po doWork() wyjść, gdy pętla wydarzenie wątku pracownik jest znowu aktywny, a przed spustem z sygnału finished() jest obsługiwany).

Podejrzewam, że jest to przypadek, ale chcę potwierdzić.

Dzięki!

Odpowiedz

7

Pętla zdarzeń wątku roboczego zostanie zablokowana, tzn. Nie będzie można przetworzyć żadnych zdarzeń (w tym tych, które są używane do "oczekujących w kolejce" połączeń między sygnałami i gniazdami, co otrzymujesz, gdy robisz sygnał -lotowe połączenia między wątkami), chyba że samemu wywołasz wywołanie obiektu pętli zdarzeń.

Można jednak nadal wykonywać w swoim wątku roboczym sloty uruchomione przez sygnały wysyłane z wątku roboczego, ponieważ są to zwykłe wywołania funkcji i nie wymagają uruchomionej pętli zdarzeń.