2009-12-14 12 views
15

Niedawno natknąłem się na ten problem, o czym wspomniałem w tym tytule. Próbowałem przy użyciu QThread :: terminate(), ale po prostu NIE mogę zatrzymać wątku, który jest w martwej pętli (powiedzmy, podczas (1)).Jak mogę zakończyć QThread

wielkie dzięki.

+0

Retagged dodać więcej wspólnego "qt" tag. – ChrisV

+2

Dokument Qt mówi: "Ostrzeżenie: ta funkcja jest niebezpieczna, a jej użycie jest odradzane." Wątek może zostać zakończony w dowolnym punkcie ścieżki kodu, wątki mogą zostać przerwane podczas modyfikowania danych. Nie ma szans na wyczyszczenie wątku po samodzielnie, odblokuj dowolne zawieszone muteksy itp. Krótko mówiąc, użyj tej funkcji tylko, jeśli jest to absolutnie konieczne, Zakończenie można jawnie włączyć lub wyłączyć, wywołując QThread :: setTerminationEnabled(). Wywołanie tej funkcji, gdy zakończenie jest wyłączone powoduje odłożenie zakończenia, do momentu zakończenia połączenia. " –

Odpowiedz

0

Czy próbowałeś exit lub quit?

+0

cytat z dokumentu pomocy QT: "Ta funkcja nic nie robi, jeśli wątek nie ma pętli zdarzeń" Może działać, w przypadku pętli zdarzeń. Ale jeśli chcę zakończyć to, zanim wątek zakończy swoją pracę, jak mam to zrobić? wielkie dzięki. Mój drogi. – user230938

+0

W rzeczywistości te dwie funkcje są używane do powrotu z pętli zdarzeń po wywołaniu komendy exec. –

0

Czy wątek zadzwonił pod numer QThread::setTerminationEnabled(false)? To spowodowałoby opóźnienie wątku w nieskończoność.

EDYCJA: Nie wiem, na jakiej platformie jesteś, ale sprawdziłem implementację QThread :: terminate dla systemu Windows. Zakładając, że wątek faktycznie był uruchomiony, a zakończenie nie zostało wyłączone za pomocą powyższej funkcji, jest to w zasadzie owinięcie wokół TerminateThread() w interfejsie API systemu Windows. Ta funkcja akceptuje brak szacunku z żadnego wątku i ma tendencję do pozostawiania bałaganu z powodu wycieku zasobów i podobnego stanu zwisającego. Jeśli nie zabija wątku, masz do czynienia z wywołaniami zombie (najprawdopodobniej zablokowanymi we/wy) lub masz gdzieś jeszcze większe problemy.

+0

Nie, i jestem pewien, że wątek może zostać zakończony. Dzięki. – user230938

+0

i wywołuję go setTerminationEnabled (true); – user230938

12

Przerwanie wątku jest łatwym rozwiązaniem do zatrzymania operacji asynchronicznej, ale zwykle jest to zły pomysł: wątek może wykonywać wywołanie systemowe lub może być w trakcie aktualizowania struktury danych po jej zakończeniu, co może pozostawić program lub nawet system operacyjny w niestabilnym stanie.

Spróbuj przekształcić swoją chwilę (1) na chwilę (isAlive()) i spraw, aby isAlive() zwrócił false, gdy chcesz, aby wątek został opuszczony.

+0

Witaj, RPG. Przykład while (1) to tylko jeden przypadek. Naprawdę chcę tylko zakończyć wątek, który wykonuje ciężkie obliczenia, które potrwają bardzo długo. Po prostu chcę to zatrzymać, zanim skończę egzekucję. Dzięki. ps: Widziałem wskazówkę, którą daje Rocknroll - użyj rury, aby zatrzymać Qthread. Ale nigdy nie znajduję rozwiązania. – user230938

+0

Spróbuj dodać coś podobnego do punktów przerwania w swojej ciężkiej funkcji obliczeniowej: http://www.justsoftwaresolutions.co.uk/threading/thread-interruption-in-boost-thread-library.html – rpg

+0

Tak, zgadzam się z tym, co zostało powiedziane tutaj. Przerwanie wątku na twardą ścieżkę nigdy nie jest dobrą rzeczą. –

0

Aby użyć anonimowych rur

int gPipeFdTest[2]; //create a global integer array 

Jako przypadku, w którym zamierza się utworzyć przewody użyciu

if(pipe(gPipeFdTest) < 0) 

{ 

perror("Pipe failed"); 

exit(1); 

} 

Powyższy kod utworzenia rury, który ma dwa końce gPipeFdTest [0] do odczytu i gPipeFdTest [1] do pisania. To, co możesz zrobić, to funkcja uruchomiona, aby odczytać potok za pomocą wybranego wywołania systemowego. A skąd chcesz wyjść z tego trybu, skonfiguruj go do pisania za pomocą polecenia systemowego write. Użyłem wybrania systemowego do monitorowania końca odczytu rury, ponieważ pasuje to do mojej implemetacji. Spróbuj dowiedzieć się wszystkiego w swojej sprawie. Jeśli potrzebujesz dodatkowej pomocy, daj mi znać.

Edytuj:

Mój problem był podobny do twojego. Miałem chwilę (1) pętlę i inne rzeczy, które wypróbowałem potrzebne muteksy i inne fantazyjne wielowątkowość mumbo jumbo, co dodało złożoności i debugowanie było koszmarem. Użycie rur uwolniło mnie od tych złożoności, oprócz uproszczenia kodu. Nie twierdzę, że to najlepsza opcja, ale w moim przypadku okazała się najlepszą i najczystszą alternatywą. Zostałem podsłuchany przez moją aplikację przed tym rozwiązaniem.

0

QThreads może zakleszczać się, jeśli zakończy się "naturalnie" podczas zakończenia.

Na przykład w systemie Unix, jeśli wątek oczekuje na wywołanie "przeczytane", próba zakończenia (sygnał uniksowy) spowoduje przerwanie wywołania "odczytu" z kodem błędu, zanim wątek zostanie zniszczony.

Oznacza to, że wątek może nadal osiągać swój naturalny punkt wyjścia podczas kończenia. Gdy to zrobi, zostanie osiągnięty zakleszczenie, ponieważ niektóre wewnętrzne muteksy są już zablokowane przez wywołanie "zakończ".

Moje obejście polega na upewnieniu się, że wątek nigdy nie zostanie zwrócony, jeśli został zakończony.

while(read(...) > 0) { 

    // Do stuff... 
} 

while(wasTerminated) 
    sleep(1); 

return; 

wasTerminated tutaj jest faktycznie realizowany nieco bardziej złożone, stosując ints atomów:

enum { 

    Running, Terminating, Quitting 
}; 

QAtomicInt _state; // Initialized to Running 

void myTerminate() 
{ 
    if(_state.testAndSetAquire(Running, Terminating)) 
    terminate(); 
} 

void run() 
{ 
    [...] 

    while(read(...) > 0) { 

    [...] 
    } 

    if(!_state.testAndSetAquire(Running, Quitting)) { 
    for(;;) sleep(1); 
    } 
}