2017-10-05 59 views
5

根據以下文章發送的信號被服務,只有當前正在執行的時隙完成。
Wait for a SLOT to finish the execution with Qt爲什麼socket :: readyRead()的新信號被執行,即使它的早期插槽仍在處理?

我有一個基於ssl套接字的客戶端 - 服務器通信應用程序,它是單線程的。

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

客戶端&服務器發送對方一些自定義消息。無論何時發送或接收消息,他們都會發送ACK字節(00)。
大多數時候,我注意到當Read()處於執行期間時,下一個readyRead()送達!我在開始& myObject->Read()結束時提供調試語句。他們確認,再次調用開始調試&。用斷點觀察也是如此。

當收到太多的數據時,遞歸堆棧幀會被創建爲太多的Read() s。它會減慢應用程序GUI或崩潰。
通常,當客戶端嘗試發送ACK作爲myObject->Read()的一部分時,會發生此遞歸。在那段時間readyRead()是偶然發信號&也得到服務。然而前一個信號的時隙仍在處理中。

問題

  • 是否有可能爲Qt框架,以滿足一個信號,當槽仍然是中途(單線程)之間?
  • 如何解決這個套接字的具體情況?

注意
- 默認情況下爲單一線程,Qt::ConnectionTypeDirectConnection。我也嘗試過QueuedConnection,但結果是一樣的。
- myObject.Read()是相當複雜的,並有許多其他函數調用。如果這是造成問題,那麼讓我知道我應該尋找什麼。編寫它的實際代碼是不切實際的。

+1

它可能會幫助https://stackoverflow.com/questions/11230080/qobject-based-class-has-a-queued-connection-to-itself –

+0

如果'myObject-> Read()'被調用,而你是在已經在其中的情況下,您可能在某個時間點對事件循環進行了控制。你可以添加函數的代碼嗎? –

+0

@BenjaminT,有很多東西與Qt無關,但是'Read()'方法的核心功能。編寫代碼是不切實際的,因爲裏面有幾種方法。但是,如果事件循環可以在插槽仍在執行時進行控制,怎麼可能呢?你可以建議,這是可能的方式。可能是我可以嘗試看看那些。 – iammilind

回答

2

readyRead()的遞歸調用是由於事件循環在兩者之間釋放而發生的。繼職能導致事件循環中解脫出來:

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

第1是可以理解的,因爲它是用於那些。但第二個flush()是一個驚喜。它的documentation並沒有這樣說。至少在我的調試中顯示,只要flush()被調用,後續的readyRead()就會被調用和照顧。在Qn中也可以看到。

processEvent()是爲了在高負載數據期間使GUI更加靈敏。但似乎我們需要爲此做出另一種選擇。