Backgroundworker Canceln

  • VB.NET

Es gibt 6 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    Backgroundworker Canceln

    Hallo,

    in einer Klasse läuft ein Backgroundworker Asyncron. Dieser wird initialisiert und gestartet, sobald ein UserForm geöfnet wird.

    Beim Schließen des UserForms werden gleich mehrere Userform-Subs aufgerufen, um die Backgroundworker zu beenden:

    FormClosing, FormClosed, Closing, Closed

    In allen Subs wird der Background-Worker mit CancelAsync beendet.

    Der Backgroundworker selbst läuft wie folgt:

    VB.NET-Quellcode

    1. Private Sub myWorker_DoWork(sender As Object, e As DoWorkEventArgs) Handles myWorker.DoWork
    2. Do
    3. ' Weitere Befehle
    4. System.Threading.Thread.Sleep(100)
    5. Loop While myWorker.CancellationPending = False And myWorker_Cancel = False
    6. End Sub


    Sobald CancellationPending auf True steht sollte der Backgroundworker beendet werden. Die Ausführung der Einzelnen Befehle innerhalb der Do-Loop Schleife sind in wenigen Millisekunden erledigt.

    Dennoch wird beim Beenden stets ein System.ObjektDisposedException angezeigt.

    Der Fehler wird auch dann angezeigt, wenn nach dem Beenden des Backgroundworkers ( CancelAsync ) mit Sleep(1200) ganze 12 Sekunden gewartet wird.

    Um ganz sicher zu gehen, wurde zusätzlich vor dem Ausführen des Befehls CancelAsync die Variable myWorker_Cancel auf true gesetzt.

    Kann mir jemand erläutern, wie ein Backgroundworker gecancelt werden kann?

    Vielen Dank
    Um ein Backgroundworker zu beenden, ruft man CancelAsync(). Den Bgw muss Cancellation erlauben, dafür muss mann WorkerSupportsCancellation=True setzen.

    Wenn CancelAsync() gerufen wird, wird die Property CancellationPending aufTrue gesetzt.

    Man soll dann in der DoWork Methode (in der Regel einer Schleife) checken nach dem Status von CancellationPending.

    Hier ein sehr einfachen Beispiel:

    VB.NET-Quellcode

    1. Imports System.ComponentModel
    2. Public Class Form1
    3. private WithEvents bgw as BackgroundWorker
    4. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    5. bgw = new BackgroundWorker With {
    6. .WorkerSupportsCancellation = true
    7. }
    8. bgw.RunWorkerAsync()
    9. Button1.Enabled=False
    10. End Sub
    11. Private Sub bgw_DoWork(sender As Object, e As DoWorkEventArgs) Handles bgw.DoWork
    12. do
    13. System.Threading.Thread.Sleep(100)
    14. Loop while not bgw.CancellationPending
    15. End Sub
    16. Private Sub bgw_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles bgw.RunWorkerCompleted
    17. MessageBox.Show("BGW beendet")
    18. Button1.Enabled=True
    19. End Sub
    20. Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    21. bgw.CancelAsync()
    22. End Sub
    23. End Class
    Life doesn't give you a datasheet. Sometimes the docs are wrong and you have to try it.
    @BigBen2003 Ein BackgroundWorker ist ein Relikt aus der Steinzeit.
    Ich empfehle die Verwendung eines richtigen Threads, der funktioniert dann mit solcher Schleife wie gewollt.
    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!
    Ich bin da nicht ganz mit dir. BGW ist m.M.n nicht aus der Steinzeit. Ich glaube ist eher eine Sache des Context (wie fast alles in der programmierung).

    Mein Motto:
    BE PRAGMATIC


    Hier ein Ausschnit aus ein SO Post (die ich super finde) über diese Thematik:


    1. Use BackgroundWorker if you have a single task that runs in the background and needs to interact with the UI. The task of marshalling data and method calls to the UI thread are handled automatically through its event-based model. Avoid BackgroundWorker if...
      • your assembly does not have or does not interact directly with the UI,
      • you need the thread to be a foreground thread, or
      • you need to manipulate the thread priority.
    2. Use a ThreadPool thread when efficiency is desired. The ThreadPool helps avoid the overhead associated with creating, starting, and stopping threads. Avoid using the ThreadPool if...
      • the task runs for the lifetime of your application,
      • you need the thread to be a foreground thread,
      • you need to manipulate the thread priority, or
      • you need the thread to have a fixed identity (aborting, suspending, discovering).
    3. Use the Thread class for long-running tasks and when you require features offered by a formal threading model, e.g., choosing between foreground and background threads, tweaking the thread priority, fine-grained control over thread execution, etc.


    Die "built-in" Funktionalität von Bgw, macht ihm wohl nutzbar in vielen Szenarios wo ein Thread unnötige zusätzliche Config(=code) bräuchte.
    Life doesn't give you a datasheet. Sometimes the docs are wrong and you have to try it.
    Hallo,

    vielen Dank für die vielen guten Informationen und Code-Beispiele.

    Konkret brauche ich den Backgroundworker für einen Dataset. Falls im Dataset eine noch nicht übernommene Änderung vorliegt, soll eine Änderungs-Anzeige im Formular sichtbar gemacht werden. Leider bietet das Dataset selbst nur drei Events an: Disposed, Initialized und MergeFailed

    Eine Methode "HasChanges" existiert bereits in einer eigenen Klasse, die von einem Dataset etwaige noch nicht gespeicherte Änderungen ermitteln kann.

    Habe schon mit dem Gedanken gespielt, ob man nicht die Methode, mit der Änderungen jeglicher Art (insert, update, Delete) in die Tabellen übertragen werden, überlade und in dem Zusammenhang ein eigenen Event auslöse. Dann müsste das DataSet vier Events haben. Aber es ist bislang nur ein Hirngespinst.

    Ich wünsche allen einen guten Rutsch ins neue Jahr 2018 und ein gesundes erfolgreiches neues Jahr.
    @BigBen2003 Auch der BGW kann Events senden, dazu musst Du das Senden von Events erlauben und dann das Event natürlich für Deinen speziellen Fall interpretieren.
    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!