Rzucanie wyjątku z wątku Qt

0

Witam, mam mały problem z rzucaniem wyjątku z innego wątku. Sytuacja jest taka. Mam program Server, który jest serwerem. Jest klasa Client (to nie jest program klient, tylko klasa, gdzie przechowuję dane klientów podłączonych do serwera) oraz klasę Ping (chodzi w nowym wątku i cały czas pinguje dopóki jest połączenie). Coś takiego

//pseudokod

//metoda w klasie Server
void addClient() {
   QTcpSocket * incoming = //... przechwytywanie polaczenia
  
   Client * c = new Client(incoming);
   try {
      c->ping();
   } catch ( ClientNotRespondException & e ) {
     std::cout<<"stracono polaczenie";
   } 
}
//..

class Client {
   QTcpSocket * socket;
   Ping * pinger;

   QString ip;
   QString nickname;
 
  //itd, pomijam inicjalizacje

   void ping() {
       pinger->start(); //startuje watek pingowania
   }
};

class Ping : QThread
{ 
   QTcpSocket * socket; //socket pingowany
   
   void run() {
     //wysylanie pinga
     //...
       throw ClientNotRespondException(); //wyrzucanie wyjatku w przypadku braku odpowiedzi
  }
}

Niewyrzuca poprawnie wyjatku tylko cos takiego:

terminate called after throwing an instance of 'ClientNotRespondException'
Przerwane (core dumped)

Wynika to z tego że jest to nowy wątek bo bez wątku wyrzuca dobrze.

0

a jak tworzysz ten wątek?

0

Przepraszam, nie zaznaczylem ze klasa Ping dziedziczy po QThread. Startuje go metodą start (metoda dziedziczona z klasy QThread). Wydaje mi sie ze problem moze byc z tym ze jezeli watek dziala rownolegle z watkiem glownym, w glownym zakonczy sie wywolanie addCLient() to potem Ping nie ma jak wrocic do tej metody, choc moge sie mylic

0

To chyba nie jest najlepsze wyjście żeby dziedziczyć po QThread zobacz http://qt-project.org/doc/qt-5.0/qtcore/qthread.html

0

Ale co to zmieni? Watki mozna tworzyc na te 2 sposoby i to nic nie zmieni w moim projekcie. Chyba zeby wykorzystac sygnaly i sloty

0

Wpadlem na inny pomysl. Puszcze te pingi w osobnym watku oraz timera, ktory bedzie co jakis czas sprawdzal stan tych pingow, jezeli pinguja tzn ze polaczenie jest stabilne. Ma to sens?

1

Ma. Nie złapiesz wyjątku w wątku innym niż ten, w którym został wygenerowany.

3

Najwyraźniej nie rozumiesz o co chodzi z wyjątkami!
Wyjątki nie są sposobem na komunikację między wątkami!!! Dotyczy to wszystkich freamoworków i wszystkich języków!
Wyjątek, ma w przejrzysty sposób przetworzyć obsługę błędu, wyjątek zmienia gałąź przetwarzanego kodu dla bieżącego wątku i bez ingerencji programisty nie ma żadnego wpływu na inne wątki (no chyba, że brak obsługi wyjątku spowoduje crash :) ).

Abstrahując od faktu, że nie powinno się dziedziczyć po QThread (było o tym na forum już wiele razy), twój kod powinien wyglądać tak:

// twoja metoda przetwarzana w jakimś wątku
void run() {
    try {
        //wysylanie pinga
        //...
        throw ClientNotRespondException(); //wyrzucanie wyjatku w przypadku braku odpowiedzi
    } catch (ClientNotRespondException &e) {
        emit errorHasOccurred(e); // emitowanie sygnału informującego o błędzie (może być przekazany między watkami).
    }
}

przy czym musisz zarejestrować typ ClientNotRespondException w metadanych, by można było przekazywać wartość tego obiektu pomiędzy wątkami, za pomocą sygnałów i slotów.

0

Jasne, coś w tym stylu właśnie wymyśliłem ^^. Będę emitował sygnał w razie braku komunikacji, tak jak pokazałeś. Ale mam jeszcze jedno pytanie. Moja struktura klas wygląda tak jak powyżej w 1 poście, tj. obiekt Server ma wektor z podłączonymi klientami (wskaźniki na obiekt klasy Client) a każdy klient ma swój Pinger

Server
--vector<Client*>
----Pinger (dla każdego klienta)

I teraz moje pytanie, czy ten sygnał powinienem przechwycić w klasie Client a potem przesłać go do Servera (zeby usunąc wpis z vectora z clientami) czy bezpośrednio z Pingera do Servera? (z tym że będę musiał potem przeszukać wektor w poszukiwaniu tego własciwiego klienta)

1 użytkowników online, w tym zalogowanych: 0, gości: 1