2012-04-03 41 views
4

這種情況:Qt:如果你發送信號太快會發生什麼?

  • 你有一個長期運行的計算在後臺線程中運行。
  • 該計算髮送一個信號,例如,每100毫秒刷新一個GUI元素。
  • 假設它發出100個這樣的信號。
  • 正在重繪的小部件需要超過100毫秒才能重繪;讓我們說1秒。

在事件循環中會發生什麼?信號調用是否「堆積」直至全部執行(即100秒)?是否有任何機制來「放棄」事件?

回答

4

用戶事件永遠不會被丟棄。如果您排隊發出的信號事件的速度超過您可以處理它們的速度,那麼您的事件隊列將會增長,直到內存不足並且程序崩潰。但值得注意的是,如果系統負載很重,QTimer將跳過超時事件。在某種程度上,這可能有助於調節您的吞吐量。

您也可以考慮將反饋從一個線程發送到另一個線程(可能是確認),並根據消費者線程背後的程度在生產者線程中手動調整您的時間。或者,您可以使用隱喻大錘並切換到阻塞排隊連接。

3

在您的示例中,您可以測量小部件中的繪圖時間。如果繪圖需要例如240毫秒,那麼您可以快速處理下2個信號而不繪製任何東西。這樣信號就不會堆積起來。

編輯:

居然有我的解決方案一個小問題。最後的信號應該總是會導致重繪,否則當計算完成時,小部件會顯示錯誤的數據。

當一個信號被跳過時,一個單發定時器可以例如以150ms的間隔啓動。當由於信號而完成重繪時,該計時器將被停止。所以在最後一次重繪信號之後,這個單次計時器會引起最終狀態的繪製。我想這會起作用,但這會很複雜。

啓動一個簡單的計時器來做計算開始時的重繪很可能是一個更好的方法。如果小部件的繪圖需要很多時間,則可以根據繪製時間動態調整定時器間隔。

+0

+1。我想我比我提出的任何東西都更喜歡這種解決方案。儘管如此,您可以進一步將計算頻率與繪圖頻率完全分離。只需緩存最後發出的值,然後根據計時器重新繪製。 – cgmb 2012-04-03 20:54:17

+0

最好的方法確實取決於案例。使用QTimer重新繪製將變得簡單,因此是一個很好的解決方案,如果重繪必須不斷進行並且重畫不需要太多時間。但是如果通常根本不需要重新繪製,然後有時會出現突發變化,需要進行相當大的重繪,那麼我提出的解決方案可能會更好。 – 2012-04-03 21:11:03

+0

我在我的解決方案中發現問題,並在答案中添加了更多文本。 – 2012-04-03 21:29:14

相關問題