Unter-Schleife per Knopfdruck beenden

  • Wie beendet man eine "Unter"-Schleife per Knopfdruck?

    Im Demo läuft die Hauptschleife der GUI. Wenn man den Button "OK" klickt, wird die TestFunc1() gestartet, in der dann für 10 Sekunden die Unter-Schleife läuft. Wie kann man die Unter-Schleife vorzeitig beenden?

    Ich habe es mit einer globalen Variablen "$g_bCancel" versucht, die beim Klick auf den Close-Button (das "rote" X) auf True gesetzt wird. In der Unter-Schleife wird $g_bCancel abgefragt und bei True sollte die Unter-Schleife beendet werden. Ich habe für die GUI den MessageLoop Modus und den OnEvent Modus probiert, leider kommt das "True" in der Unter-Schleife nicht an (in der Hauptschleife der GUI kommt es an).

    Als Demo habe ich ein Beispiel aus der AutoIt Hilfe als Basis genommen und angepasst.

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.

  • Du solltest in Windows Events prinzipiell keine Schleifen verwenden. Das sorgt nur dafür dass sich das Programm aufhängt und Events nicht mehr richtig funktionieren.

    Stattdessen kannst du eine Variable in dem Event setzen um dann deine gewünschte Funktion aufzurufen:

    Noch schöner (und bei einer größeren GUI) ist natürlich eine Funktion die das managed.

    2 Mal editiert, zuletzt von Yjuq (25. November 2020 um 23:51)

  • Du solltest in Windows Events prinzipiell keine Schleifen verwenden. Das sorgt nur dafür dass sich das Programm aufhängt und Events nicht mehr richtig funktionieren.

    Naja, das ist "relativ". Ich denke, dass es gängiges Vorgehen ist, in einem Button-Click auch Routinen zu starten, in denen Schleifen benutzt werden. Das wird normalerweise nicht auffallen, weil es selten Schleifen sind, die man abbrechen möchte. Oft will man sogar, dass die weitere Ausführung erst erfolgt, nachdem die Schleife beendet ist. In Scripts mit MessageLoop Modus sehe ich das sehr oft.

    Dennoch hast du recht, dass man das wohl prinzipiell nicht tun sollte, vorallem bei Events, die oft ausgelöst werden, wie z.B. Win-Messages. Und offensichtlich ist es auch bei einem Button-Click besser, falls man wie hier eine Schleife vorzeitig beendet können soll. (Konkret geht es um einen Download, der im Falle eines Falles abgebrochen werden soll.)

    Danke für deinen Code-Snippet. Für eine bessere Übersicht habe ich für "Cancel" einen eigenen Button eingebaut und Kommentare entfernt.

    Das funktioniert Im OnEvent Modus soweit gut, die Unter-Schleife wird auf Knopfdruck beendet ($g_bCancel) und auch der Close-Button der GUI reagiert. Leider habe ich es im MessageLoop Modus nicht hinbekommen. Hast du da auch eine Idee?

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.

  • Naja, das ist auch ganz simpel. Im prinzip werden die neuen Events gefetcht nachdem du GuiGetMsg() aufrufst. Demnach musst du es nur aufrufen und auf Events reagieren:

    Sleep() verhindert aber das sofortige schließen. Ist genauso ein Fall den du nicht in Events setzen möchtest. Hier mal eine Variation mit einen richtigen Timer:

    Solche Sachen lassen sich aber mit einer "Manager" Funktion, welche AutoIt Skript von dem Windows Events trennt, ziemlich einfach lösen.

  • Beeindruckend! :rock:

    Deine beiden Code-Snippets habe ich kurz durchgesehen. Beide werde ich später ausprobieren und gedanklich verarbeiten, damit ich auch verstehe, was da genau passiert. Das kann eine Weile dauern. Kannst du vielleicht zwischenzeitlich erklären, wie so eine Manager Funktion aussieht und was sie tut?

    Solche Sachen lassen sich aber mit einer "Manager" Funktion, welche AutoIt Skript von dem Windows Events trennt, ziemlich einfach lösen.

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.

  • AutoIt
    Func TestFunc1()
      ...
      Local $timer = TimerInit()
      Do
        If TimerDiff($timer) > 250 Then
          ...
        EndIf
        events()
      Until $iCnt = 40 ; Läuft ca. 10 Sekunden.
    EndFunc   ;==>TestFunc1

    Coole Sache! 8) An dieser Möglichkeit hatte ich gearbeitet, aber nichts gefunden. Gewollt war ein "DoEvents" (Visual Basic), das die Schleife unterbricht um die Events auszuwerten. Dabei hatte ich versucht, mit 25x Sleep(10) eine Unterbrechung/Auswertung zu erreichen, was natürlich funktionierte. Nun weiß ich, dass es an der ständigen Abfrage von "events()" gelegen hat. - Da soll mal jemand drauf kommen. Naja, man könnte schon drauf kommen, aber ich bin nicht drauf gekommen. :(

    Deine Code-Snippets will ich unbedingt in meine Tipps-Sammlung aufnehmen! (= große Ehre) :) Mir will einfach keine Bezeichnung einfallen, mit der ich das wiederfinde, wenn ich es in einem Jahr oder so wieder brauche. Vielleicht nehmen ich "Schleife beenden, Events in Schleife auswerten". Mal sehen.

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.

  • Dank deiner Tipps habe ich die Zusammenhänge nun verstanden und noch eine Alternative mit GUIRegisterMsg() entwickelt. Als kleiner Vorteil kann man bei dieser Methode Sleep(250) problemlos in der Unter-Schleife benutzen, die Reaktionen vom Cancel- oder Close-Button treten trotzdem unmittelbar ein. Wichtig ist, dass die Funktion mit der Unter-Schleife (TestFunc1()) in der Hauptschleife aufgerufen wird.

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.

  • Solche Sachen lassen sich aber mit einer "Manager" Funktion, welche AutoIt Skript von dem Windows Events trennt, ziemlich einfach lösen.

    Yjuq Wie sieht denn eine Manager Funktion aus und was tut sie?

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.

  • Bitnugger 10. Dezember 2020 um 14:12

    Hat den Titel des Themas von „Unter-Schleife per Kopfdruck beenden“ zu „Unter-Schleife per Knopfdruck beenden“ geändert.