none
Break Button - Application.DoEvents RRS feed

  • Frage

  • Hallo zusammen.

    Ich möchte die Verarbeitung in einer Form abbrechen, dadurch das ein Button geklickt wird.
    Nun habe ich oft gelesen, das die faule Methode mit Application.DoEvents nicht das Richtige ist.
    Ich suche schon eine weile im Internet, bin aber eher unsicher wie.

    Kann mir jemand sagen wie ich zu der Info komme, ob der 'Abbbrechen'  Button gedrückt wurde?

    Gruss Peter

    Donnerstag, 12. März 2015 12:41

Antworten

  • Hallo Peter,

    sinnvoller (und vermutlich für Dich einfacher) wird der BackgroundWorker sein. Er unterstützt bereits ein Abbrechen über WorkerSupportsCancellation und das Setzen von CancellationPending im DoWork. So ist auch sichergestellt, das der Abbruch nicht zur Unzeit kommt. Status-Benachrichtigungen kannst Du über das ReportProgress Ereignis auf dem Formular ausgeben.

    Von einer "Modul-Variable" sollte man Abstand nehmen... ebenso wie von Thread Abort (worauf auch die Dokumentation deutlich hinweist)

    Gruß Elmar

    • Als Antwort markiert peter haus Freitag, 13. März 2015 08:50
    Donnerstag, 12. März 2015 15:33
    Beantworter

Alle Antworten

  • Hallo,

    da ich keine Ahnung habe wie dein Vorgang aussieht, würde ich mal sagen dass es da zahlreichen Möglichkeiten gibt.

    Läuft deine Aufgabe im selben Thread wie die UI, oder in einem extra Thread? Welche Funktion verwendest du?

    Allgemeine Hinweise:

    -- Aufgabe läuft in weiteren Hintergrundthread:

    -- asynchrone Funktionen (ohne Task!) wie bei WebClient.DownloadFileAsync -> Benutze: WebClient.CancelAsync()


    © 2015 Thomas Roskop

    Germany // Deutschland

    Donnerstag, 12. März 2015 14:20
  • Hallo Thomas,

    ich möchte in der angezeigten Form, durch das anklicken eines Buttons die Möglichkeit haben, die Form zu beenden. In der Form läuft in einem Loop das Ausdrucken von Daten.

    Ich hatte heute bei im Internet schon mal eine Möglichkeit gesehen.
    Die sah ungefähr so aus, das Threading.Tasks.Task.Factory.StartNew() die Button_Click Event übergeben wurde.
    Ich finde es leider nicht mehr.

    Die Funktion zum Drucken kann ich wohl auch in einen BackgroundWorker ausführen.
    Besser würde es mir gefallen, wenn ich in einem Button Click eine Modul-Variable setzen könnte, und dadurch den Loop verlassen.

    Danke und Gruss
    Peter

    Donnerstag, 12. März 2015 14:47
  • Hallo Peter,

    sinnvoller (und vermutlich für Dich einfacher) wird der BackgroundWorker sein. Er unterstützt bereits ein Abbrechen über WorkerSupportsCancellation und das Setzen von CancellationPending im DoWork. So ist auch sichergestellt, das der Abbruch nicht zur Unzeit kommt. Status-Benachrichtigungen kannst Du über das ReportProgress Ereignis auf dem Formular ausgeben.

    Von einer "Modul-Variable" sollte man Abstand nehmen... ebenso wie von Thread Abort (worauf auch die Dokumentation deutlich hinweist)

    Gruß Elmar

    • Als Antwort markiert peter haus Freitag, 13. März 2015 08:50
    Donnerstag, 12. März 2015 15:33
    Beantworter
  • Hallo Elmar.

    Deine Aussage ist eindeutig.

    Falls du die Variante kennst, die ich im Internet gesehen hatte.
    Die sah ungefähr so aus, das Threading.Tasks.Task.Factory.StartNew() die Button_Click Event Routine übergeben wurde. Würde mich das sehr interessieren wie das ging.
    Vielleicht kennst du ein Code Schnipsel (auch C#).
    Das Beispiel das ich gesehen hatte war in C#. Ich konnte es leider nicht nach VB übersetzen und habe es dann dummerweise gelöscht.

    Danke und herzliche Grüsse
    Peter

    Donnerstag, 12. März 2015 17:30
  • Hallo Peter,

    welches Beispiel Du gefunden hast, ist für andere kaum zu bestimmen, denn dazu gibt es Legionen von Beispielen. Normalerweise wird ein Click Ereignis nicht für einen neuen Thread verwendet. Das findet man mehr im Rahmen der Asynchronen Programmierung, die ab Visual Basic 2012 und .NET 4.5 verfügbar sind, jedoch i.a . in anderem Kontext.

    Im einfachsten Falle ruft man eine spezielle Methode auf, und übergibt ihr ein CancellationToken, damit man es abbrechen kann:

        Dim cts As CancellationTokenSource
        Dim theTask As Task
    
        Private Sub executeButton_Click(sender As Object, e As EventArgs) Handles executeButton.Click
            cts = New CancellationTokenSource
            theTask = System.Threading.Tasks.Task.Factory.StartNew(
                Sub()
                    AsychroneMethode(cts.Token)
                End Sub, cts.Token, TaskCreationOptions.LongRunning)
    	End Sub
    
        Private Sub CancelButton_Click(sender As Object, e As EventArgs) Handles cancelButton.Click
            If cts IsNot Nothing AndAlso cts.IsCancellationRequested = False Then
                Console.WriteLine("Cancel Task")
                cts.Cancel()
            End If
        End Sub
    
        Private Sub AsychroneMethode(token As CancellationToken)
            Dim i As Integer
            While Not token.IsCancellationRequested
                Thread.Sleep(1000)
                i += 1
                Console.WriteLine("Loop {0} ", i)
            End While
        End Sub
    

    Wobei einiges mehr zu tun wäre, um der Methode wirkliches Leben einzuhauchen.

    Wenn Du bereits eine funktionierende Windows Forms Lösung hast, die "nur" in den Hintergrund gelegt werden soll, ist es vermutlich für Dich einfacher, es mit einem BackgroundWorker zu versuchen. Denn sowohl Basis-TPL wie asynchrone Programmierung mit .NET 4.5 - wobei man letzteres bevorzugen sollte - erfordern einige Zeit für die Einarbeitung.

    Gruß Elmar

    Donnerstag, 12. März 2015 18:21
    Beantworter
  • Hallo Elmar,

    vielen Dank für deine Antwort und das zusätzliche Beispiel.

    Ich habe es gerade mal getestet und es funktioniert auch.
    Es hat mich sehr interessiert, weil ich es gestern nicht hin bekam.

    Nun werde ich mir den BackgroundWorker anschauen.

    Viele Grüsse
    Peter

    Freitag, 13. März 2015 08:49