2017-10-05 98 views
5

Zgodnie z następującym postem wysyłany sygnał jest wyświetlany dopiero po zakończeniu aktualnie wykonywanego gniazda.
Wait for a SLOT to finish the execution with QtDlaczego nowy sygnał dla socket :: readyRead() jest wykonywany, nawet jeśli jego wcześniejsze gniazdo jest nadal przetwarzane?

Mam aplikację komunikacyjną klient-serwer opartą na gnieździe ssl, który jest pojedynczy wątek.

connect(socket, &QSslSocket::readyRead, [&]() { myObject.Read(); }); 

Client Server & wysłać sobą pewne komunikaty niestandardowe. Za każdym razem, gdy wiadomość zostanie wysłana lub odebrana, wysyła ona ACK bajtów (00).
W większości przypadków zauważam, że kiedy Read() jest pomiędzy wykonaniem, pojawia się następny readyRead()! Umieszczam instrukcje debugowania na początku & koniec myObject->Read(). Potwierdzają, że rozpoczęcie debugowania ponownie się nazywa &. To samo dotyczy punktów przerwania.

Po otrzymaniu zbyt dużej ilości danych tworzona jest ramka rekursywna o zbyt dużej liczbie Read() s. Spowalnia działanie GUI aplikacji lub awarie aplikacji.
Zazwyczaj ta rekurencja ma miejsce, gdy klient próbuje wysłać potwierdzenie ACK jako część myObject->Read(). W tym czasie zostaje również zasygnalizowany przypadek readyRead(). Jednak gniazdo poprzedniego sygnału było nadal przetwarzane.

Pytania:

  • Czy jest możliwe, aby zaspokoić Qt framework sygnału pomiędzy nimi, gdy gniazdo jest nadal w połowie drogi (pojedynczy wątek)?
  • Jak naprawić ten scenariusz?

Uwaga:
- domyślnie dla pojedynczych gwintów Qt::ConnectionType jest DirectConnection. Próbowałem również z QueuedConnection, ale wynik jest taki sam.
- myObject.Read() jest dość skomplikowana i ma wiele innych funkcji. Jeśli to powoduje problem, daj mi znać, czego powinienem szukać. Pisanie właściwego kodu będzie niepraktyczne.

+1

To może pomóc https://stackoverflow.com/questions/11230080/qobject-based-class-has-a-queued-connection-to -self –

+0

Jeśli 'myObject-> Read()' jest wywoływane, gdy jesteś już w nim jest prawdopodobne, że w pewnym momencie uzyskasz kontrolę nad pętlą zdarzeń. Czy możesz dodać kod funkcji? –

+0

@BenjaminT, istnieje wiele rzeczy, które nie są związane z Qt, ale podstawowa funkcjonalność wewnątrz metody 'Read()'. Pisanie tego kodu będzie niepraktyczne, ponieważ jest w nim kilka metod. Jak to jednak możliwe, że pętla zdarzeń może przejąć kontrolę, gdy boks jest jeszcze w trakcie wykonywania? Czy możesz zasugerować, w jaki sposób jest to możliwe. Być może mogę spróbować spojrzeć na te. – iammilind

Odpowiedz

2

Rekurencyjne połączenia readyRead() miały miejsce z powodu zwalniania pętli zdarzeń pomiędzy nimi. Następujące funkcje zostały powodując pętla zdarzenie zostać uwolniony:

  1. QCoreApplication::processEvents()
  2. SslSocket::flush()

The 1st jest zrozumiałe, jak to ma za to. Ale drugie flush() było całkowitym zaskoczeniem. Jego documentation nie stanowi tak. Przynajmniej w moim debugowaniu pokazano, że za każdym razem, gdy wywoływana jest nazwa flush(), późniejsza readyRead() jest wywoływana i odbierana. Zobacz również w Qn.

Urządzenie processEvent() miało sprawić, że interfejs GUI będzie bardziej responsywny podczas wysokiego obciążenia danych. Wydaje się jednak, że musimy dokonać innego wyboru.