2012-04-03 5 views
4

Hier ist die Situation:Qt: Was passiert, wenn Sie Signale zu schnell senden?

  • Sie haben eine lange Lauf in einem Hintergrund-Thread Berechnung läuft.
  • Diese Berechnung sendet ein Signal zum Beispiel zum Aktualisieren eines GUI-Elements alle 100 ms.
  • Sagen wir, es sendet 100 solche Signale aus.
  • Das neu gezeichnete Widget benötigt mehr als 100 ms zum Neuzeichnen; Sagen wir 1 Sekunde.

Was passiert in der Ereignisschleife? Rufen die Signalaufrufe an, bis sie alle ausgeführt sind (d. H. 100 Sekunden)? Gibt es einen Mechanismus zum "Ablegen" von Ereignissen?

Antwort

4

Benutzerereignisse werden nie verworfen. Wenn Sie Ereignisse aus dem abgestrahlten Signal schneller in die Warteschlange stellen, als Sie verarbeiten können, wird die Ereigniswarteschlange anwachsen, bis der Speicher voll ist und Ihr Programm abstürzt. Es ist jedoch zu beachten, dass QTimer Timeout-Ereignisse überspringt, wenn das System stark ausgelastet ist. In gewissem Maße kann dies dazu beitragen, Ihren Durchsatz zu regulieren.

Sie könnten auch in Erwägung ziehen, Feedback von einem Thread an den anderen zu senden (eine Bestätigung, vielleicht) und das Timing im Producer-Thread manuell anpassen, je nachdem, wie weit hinter dem Consumer-Thread ist. Oder Sie könnten einen metaphorischen Vorschlaghammer verwenden und zu einer blockierenden Warteschlange wechseln.

3

In Ihrem Beispiel könnten Sie die Zeichnungszeit im Widget messen. Wenn die Zeichnung beispielsweise 240 ms dauert, könnten Sie die nächsten 2 Signale schnell verarbeiten, ohne überhaupt etwas zu zeichnen. Auf diese Weise würden sich die Signale nicht aufstauen.

Edit:

Eigentlich gibt es ein kleines Problem in meiner Lösung. Das letzte Signal sollte immer zu einem Neuzeichnen führen, andernfalls würde das Widget falsche Daten anzeigen, wenn die Berechnung beendet ist.

Wenn ein Signal übersprungen wird, könnte ein Einzelschuss-Timer beispielsweise mit einem 150-ms-Intervall gestartet werden. Wenn ein Neuzeichnen aufgrund eines Signals durchgeführt wird, wird dieser Zeitgeber gestoppt. Nach dem letzten Neuzeichnen-Signal würde dieser Einzelschuss-Timer das Zeichnen des Endzustandes bewirken. Ich denke, das würde funktionieren, aber es wäre ziemlich kompliziert.

Einen einfachen Timer zu starten, um das Neuzeichnen zu machen, wenn die Berechnung beginnt, wäre wahrscheinlich ein besserer Ansatz. Wenn das Zeichnen des Widgets viel Zeit in Anspruch nimmt, könnte das Zeitgeberintervall entsprechend der Zeichenzeit dynamisch angepasst werden.

+0

+1. Ich denke, ich mag diese Art von Lösung mehr als alles, was ich vorgeschlagen habe. Sie könnten jedoch weiter gehen und die Häufigkeit der Berechnung vollständig von der Häufigkeit der Zeichnung entkoppeln. Einfach den zuletzt ausgegebenen Wert zwischenspeichern und basierend auf einem Timer neu zeichnen. – cgmb

+0

Der beste Ansatz hängt wirklich vom Fall ab. Das Redrawing mit QTimer wäre einfach und daher eine gute Lösung, wenn das Redrawing ständig durchgeführt werden muss und das Neuzeichnen nicht zu lange dauert. Aber wenn das Neuzeichnen in der Regel überhaupt nicht benötigt wird und manchmal Änderungen auftreten, die ein ziemlich schweres Neuzeichnen erfordern, dann könnte die von mir präsentierte Lösung besser sein. –

+0

Ich habe ein Problem in meiner Lösung gefunden und etwas mehr Text zur Antwort hinzugefügt. –

Verwandte Themen