2013-01-03 10 views
6

Poniższy fragment kodu rozpoczyna proces, który trwa jedną sekundę, aby zakończyć, a następnie czeka na zakończenie tego procesu przed zakończeniem. Z jakiegoś powodu następujący kod zawiesza się w p->waitForFinished(), mimo że proces się zakończył.Dlaczego nie można czekać na zakończenie procesu Qt w statycznym destruktorze?

#include <QtCore/QProcess>  

class A 
{ 
    public: 
    A(): 
     p(0) 
    { 
    } 

    ~A() 
    { 
     p->waitForFinished(); 
     delete p; 
    } 

    void start() 
    { 
     p = new QProcess(0); 
     p->start("sleep 1"); 
    } 

    QProcess *p; 
}; 

int main(void) 
{ 
    static A a; 
    a.start(); 

    return 0; 
} 

Jednak jak tylko a nie jest zadeklarowane statycznie, lecz w sposób następujący:

A a; 

wywołanie waitForFinished() powiedzie. Czy jest to błąd Qt, czy jest to oczekiwane zachowanie? Podejrzewam, że jakaś logika wymagana do wykrycia, czy aplikacja zakończyła się pomyślnie, jest już zniszczona po wywołaniu destruktora A.

+0

jaki system operacyjny? .......... – neagoegab

+0

@neagoegab Linux –

Odpowiedz

10

Próbowałeś oczyścić wątek utworzony przez QProcess na dwa różne sposoby w tym samym czasie, więc jest to błąd w twoim programie.

Odłączyłeś wątek, powracając z main (co kończy wszystkie wątki w procesie, odłączając je, jeśli można je dołączyć).

Oczyściliśmy wątek QProcess, łącząc go przez waitForFinished.

Możesz odłączyć wątek lub możesz do niego dołączyć, ale nie możesz zrobić obu, nawet pośrednio. Wygląda na to, że rozłączenie wygrywa, a dołączenie się zawiesza.

Najprawdopodobniej dlatego, że QProcess używa własnego sygnału zakończenia, a nie wbudowanego w bibliotekę wątków. Tak więc powrót z main kończy wątek, zanim będzie mógł wysłać ten sygnał zakończenia, pozostawiając funkcję waitForFinished oczekiwania na sygnał, który nigdy nie zostanie wysłany.

Zasadniczo wątki nie powinny być tworzone w konstruktorach ani oczyszczane w destruktorach. Wynika to przede wszystkim z tego, że terminy tych operacji wymagają bardziej wyraźnej kontroli niż jest to możliwe. I nigdy nie powinny być tworzone przed main startami ani oczyszczonymi po powrocie do stanu z main - znowu dlatego, że musisz kontrolować kontekst, w którym te rzeczy się zdarzają.

Powiązane problemy