Wie kann man Endlosschleifen beim Schließen abbrechen?

  • VB.NET

Es gibt 13 Antworten in diesem Thema. Der letzte Beitrag () ist von Samus Aran.

    Wie kann man Endlosschleifen beim Schließen abbrechen?

    Hi,

    Ich habe ein Problem mit meinem Webbrowser in Vb 2010. Ich benutze den Webbrowser logischerweise um Seiten aufzurufen. Ich benutze eine Schleife, die den WebbrowserReadystate Wert abfragt, um das Programm so lange warten zu lassen, bis die Seite geladen ist.

    Quellcode

    1. Private Sub LoadUrl(ByVal url As String)
    2. WebBrowserListe(0).Navigate(url)
    3. wait_for_browser_completed()
    4. End Sub
    5. Private Sub wait_for_browser_completed()
    6. Do Until WebBrowserListe(0).ReadyState = WebBrowserReadyState.Complete
    7. Application.DoEvents()
    8. Thread.Sleep(1)
    9. Loop
    10. End Sub

    Jedoch kann es vorkommen, dass mal eine Seite ewig hängt, also der Readystate auf "Loading" oder "Interactive" bleibt. Auch kann es vorkommen, dass die Form vom User mit Klick auf das X geschlossen wird während die Seite noch geladen wird. In beiden Fällen läuft der Prozess im Taskmanager weiter und nur die Form schließt sich.
    Ich benutze übrigens auch noch das MyBase.Closing event um ein datei anzulegen. Ich habe eben folgendes probiert (END Befehl):

    Quellcode

    1. Private Sub Form1_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
    2. logs_speichern()
    3. End
    4. End Sub

    Das funktioniert - aber überall wird davon abgeraten "End" zu benutzen. Gibts da eine Alternative?

    Ich habe auch schon mit dem DocumentCompleted Event rumexperimentiert, jedoch ist das Event für mich unbrauchbar, da es je nach Webseite 1-XX mal ausgelöst wird.
    PS: Der Webbrowser wird zur Laufzeit dynamisch erstellt.
    Das hilft mir nicht leider nicht weiter. Ich will nämlich nicht das die Prozessorauslastung auf 100 % hochgeht wenn das Prgramm nichts weiter macht als eine Seite laden. Ich verwende manchmal auch eine Sleep() funktion (auch mit Application.DoEvents() und Thread.Sleep(1)), bei der ein Timer eine Globale integer variable hochzählt. Sobald dann ein gewisser Wert erreicht wird, hört die Schleife natürlich auf.

    Meine Hauptaugenmerk liegt zur Zeit eher auf dem "End" (was ja nicht so sauber sein soll).

    markus.obi schrieb:

    Wie kann man Endlosschleifen beim Schließen abbrechen?
    eiglich gar nicht.

    ich denke, du mußt umdenken von prozedural auf ereignisorientiert - gugge Alles über Events
    DocumentCompleted ... da es je nach Webseite 1-XX mal ausgelöst wird.
    du musst halt in den Eventargs gucken, ob es für die richtige url gefeuert wird.

    markus.obi schrieb:

    Ich habe auch schon mit dem DocumentCompleted Event rumexperimentiert, jedoch ist das Event für mich unbrauchbar, da es je nach Webseite 1-XX mal ausgelöst wird.

    Das Event ist nicht unbrauchbar, sondern dein Code ...

    DocumentCompleted ist der richtige Weg. Alles andere ist Murks!

    Das einzige was noch gehen würde: Async CTP Refresh 1 !

    Samus Aran schrieb:

    Die Prozessorauslastung geht durch sowas nicht in die Höhe, schon gar nicht auf 100%. Wenn sies bei dir tut, würde ich schnellstens den Prozessor auswechseln.

    DoEvents und Sleep ist nicht gerade die sauberste Kombination.

    Sry waren exact 50 % Auslastung (nicht 100). Das ist aber normal! Überleg dir mal wie oft er die Schleifenbedingung auswertet (so schnell er kann^^). Dass das eine sehr hässliche und unsaubere Lösung ist, stimm ich dir zu.

    ErfinderDesRades schrieb:

    markus.obi schrieb:

    Wie kann man Endlosschleifen beim Schließen abbrechen?
    eiglich gar nicht.

    ich denke, du mußt umdenken von prozedural auf ereignisorientiert - gugge Alles über Events
    DocumentCompleted ... da es je nach Webseite 1-XX mal ausgelöst wird.
    du musst halt in den Eventargs gucken, ob es für die richtige url gefeuert wird.


    Danke für den Tipp! Ich habe die Eventargs bisher nur als sender.tostring und e.tostring betrachtet (bringt nicht viel Info). Habe jetzt erst gesehen, dass bei den eventargs eine "Url" eigenschaft existiert.
    Das mit dem ereignisorientiert ist mir auch bewusst, dass das viel sauberer ist. Nur hab ich keinen blassen Schimmer wie ich von prozedural auf ereignisorientiert komme ohne dass der code 10 mal so lang wird. Ich habe bisher schon events bei Timern, trackbars, checkboxen, buttons, radiobuttons, Form (resize, close, load) benutzt. Aber diese LoadUrl() Routine befindet sich an dutzenden Stellen im Code und größtenteils nicht auf einer Ebene (verschachtelt). Da müsste ich ja alles was nach einer Loadurl() Routine kommt in eine eigene "sub" verfrachten. Kann ich mir beim besten Willen nicht vorstellen wie das gehen soll (auch nicht mit einer anderen Struktur).

    ErfinderDesRades schrieb:

    markus.obi schrieb:

    Wie kann man Endlosschleifen beim Schließen abbrechen?
    eiglich gar nicht.

    Doch, man kann.
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private Sub Form1_FormClosing(ByVal sender As System.Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles MyBase.FormClosing
    3. XXX.ExitFlag = True
    4. End Sub
    5. End Class
    6. Class XXX
    7. Public Shared ExitFlag As Boolean = False
    8. End Class
    9. Class YYY
    10. Sub ZZZ()
    11. Do
    12. If XXX.ExitFlag Then
    13. Exit Do
    14. End If
    15. ' etwas tun
    16. Loop
    17. End Sub
    18. End Class

    Natürlich muss dieser Schleifen-Exit-Code in jeder Endlosschleife implementiert werden, was allerdings einen letztenendes unsauberen Code bewirkt.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Sowas hab ich befürchtet. Geht also nur über eine zusätzliche if Bedingung in jeder Schleife, die einen boolschen Wert überprüft. (das bricht die Schleife ab und der code danach wird dann ja natürlich trotzdem ausgeführt).

    Damit wäre eigentlich alles geklärt für mich. Dann versuch ich mal alles auf ereignisorientiert umzustellen. Danke für die Hilfe an alle.