C++ / Qt: Rückmeldung an das OS bei langen Berechnungen



  • Hey,
    Ich stehe vor folgendem Problem, das ich mit meinen Kenntnissen leider noch nicht lösen kann:

    Meine Software wurde mit Hilfe von Qt erstellt. Wenn der Benutzer einen bestimmten Button drückt, muss eine aufwendige Berechnung durchgeführt werden, die 30 Sekunden bis einige Minuten in Anspruch nimmt. Die Berechnung läuft auch durch, solange man nichts "anrührt". Holt der Benutzer jedoch ein anderes Programm oder den Desktop in den Vordergrund, bleibt meine Software hängen und das OS zeigt an, dass sie keine Rückmeldung sendet.

    Vermutlich muss ich während des Rechenvorgangs dem OS scheibchenweise Rückmeldungen senden? Wie kann ich dies mit Qt, oder vielleicht der Standard Library von C++, lösen? Suche hat leider nichts ergeben, oder ich finde nicht die richtigen Stichworte.

    Danke für eure Mühen!



  • Es gibt einen Befehl unter wxWidgets der nennt sich wxYield(). Schau mal obs bei QT sowas auch gibt. Das sollte Abhilfe schaffen, wenn Du dies am Ende Deiner Schleife/Threads oder wie auch immer Du das machst aufgerufen wird.
    rya.



  • Wenn du eine Schleife durchlaufen lässt, dann könntest du hin und wieder

    QCoreApplication::processEvents(QEventLoop::AllEvents);
    

    aufrufen (gibt da auch andere Parameter, einfach mal in die Dokumentation schauen.

    Falls dir das nicht reicht und sich die "Arbeit" deines Programms gut in Schleifenform pressen lässt, könntest du auch mit einem QTimer arbeiten.

    QTimer t;
    t.start(0);//so oder so ähnlich, bin nicht mehr ganz sicher
    connect(t , SIGNAL(timeout()) , deinProgramm , SLOT(bearbeiteNächstenSchleifendurchlauf()));
    

    Zu guter letzt bliebe dir die Arbeit in einem anderen Thread übrig, dazu müsstest du dir mal die Dokumentation zu QThread anschauen. Allerdings kannst du dort wohl nicht mit Widgets arbeiten (hab's selbst noch nicht probiert, steht so in der Doku).

    Die erste Möglichkeit ist sicher die einfachste, allerdings darfst du das nicht zu oft durchführen (das verlängert die Arbeitsdauer deines Programms enorm) und nicht zu selten, sonst meldet Windows weiterhin, dass das Programm nicht reagiert (was übrigens nicht schlimm ist, es sollte im Hintergrund weiterlaufen; einfach abwarten).



  • Alle Varianten funktionieren, wobei die mit einem separaten Thread mit Abstand am schnellsten ist. Da der Benutzer die Berechnung über das Interface auch abbrechen können soll, fällt diese Möglichkeit leider weg. Die etwas langsamere Alternative reicht aber für meine Zwecke aus.

    Danke euch vielmals!!



  • elpara schrieb:

    Alle Varianten funktionieren, wobei die mit einem separaten Thread mit Abstand am schnellsten ist. Da der Benutzer die Berechnung über das Interface auch abbrechen können soll, fällt diese Möglichkeit leider weg.

    Nein. Es geht auch mit Threads. Du kannst auch mit einer Mutex geschützten Variable arbeiten, die du auf true setzt, wenn die Berechnung abbrechen soll. Du musst dann in der Berechnung diese Variable halt immer mal wieder abfragen...



  • Vielleicht kommt bei Dir QProgressDialog in Frage?

    Die Doku sagt dazu:

    A progress dialog is used to give the user an indication of how long an operation is going to take, and to demonstrate that the application has not frozen. It can also give the user an opportunity to abort the operation.



  • Phistomefel schrieb:

    Vielleicht kommt bei Dir QProgressDialog in Frage?

    Die Doku sagt dazu:

    A progress dialog is used to give the user an indication of how long an operation is going to take, and to demonstrate that the application has not frozen. It can also give the user an opportunity to abort the operation.

    Ist nur ein ganz normales Widget, das man ebenso mit Updates versorgen muss, wie den Rest des Programmes. Das Problem bliebe damit also bestehen - aber ein ProgressDialog (oder eine selbst verbaute QProgressBar) ist eine feine Sache ;).



  • Stiefel2000 schrieb:

    Ist nur ein ganz normales Widget

    Nein, das stimmt so nicht. So gesehen sind auch vergleichsweise komplexe Widgets wie ein QTableView nur "normale Widgets". Allerdings normale Widgets, bei denen man Linien, Texte, Pixmaps etc. selbst zeichnen muss und das MV-Delegate-Framework selbst nachbilden muss 😮

    ... das man ebenso mit Updates versorgen muss, wie den Rest des Programmes. Das Problem bliebe damit also bestehen ...

    Auch das stimmt so nicht. Die Ursache des Problems ist ja folgende: während der Berechnung reagiert das Widget nicht auf Fensternachrichten wie Vergrößern/Verkleinern, Neuzeichnen etc., daher glaubt Windows es sei "eingefroren". QProgressDialog bietet nun die Möglichkeit, die Berechnung in beliebige Schritte einzuteilen, wobei nach jedem "Fortschritt" (d.h. jedesmal, wenn mittels setValue ein neuer Wert gesetzt wird) die Fensternachrichten abgearbeitet werden. Und zwar genau so wie oben vorgeschlagen: es wird QApplication::processEvents aufgerufen.
    Hinzu kommen noch so praktische Dinge wie zB der vorgefertigte Abbruchmechanismus und, dass der Dialog gar nicht erst angezeigt wird, wenn die geschätzte Berechnungsdauer kleiner als bspw 4 Sekunden ist.
    Sogesehen finde ich schon, dass QProgressDialog ziemlich gut passt.


Anmelden zum Antworten