BackgroundWorker hängt

  • VB.NET

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

    BackgroundWorker hängt

    Hi,
    ich nutze einen BackgroundWorker, der SAP-Daten empfängt und in eine lokale Datenbank schreibt. Dies tut er tagelang ohne Probleme, außer die Verbindung zum SAP-Server reißt ab. Mit ein wenig Glück fängt er sich wieder, aber meistens bleibt die letzte Aktion (ruft eine Funktion in einer SAP .dll auf) dann hängen und man kann warten, bis die Bits kippen. Meine Idee war nun, den BackgroundWorker zu überwachen und diesen nach gewisser Untätigkeit grob fahrlässig zu beenden, sprich "abzuschießen" und anschließend neu zu starten. Das scheint jedoch nicht ganz so einfach zu sein. "CancellationPending" hilft hier nicht weiter, weil der BackgroundWorker ja nicht mehr lebt. Übersehe ich hier eine einfache Lösung? Im Moment schieße ich im Problemfall die ganze Anwendung via TaskManager ab, aber das soll kein Dauerzustand werden.
    An manchen Tagen gibt es zu allem Überfluss auch noch Ärger!

    Rainman schrieb:

    Übersehe ich hier eine einfache Lösung?
    Nimm einen System.Threading.Thread.
    Den kanst Du mit dem Holzhammer beenden: thread.Abort().
    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 habe einen interessanten Ansatz gefunden, den ich mal antesten werde.
    stackoverflow.com/questions/80…kground-worker-completely
    Der BackgroundWorker startet einen Thread,
    der dann mit dem Holzhammer thread.Abort() terminiert werden kann.

    Gut, man könnte den BackgroundWorker auch ganz weglassen, andererseits benötigt man vermutlich sowieso
    zwei Threads - einen zum Ausführen und einen zum Überwachen und abschießen.
    An manchen Tagen gibt es zu allem Überfluss auch noch Ärger!

    Rainman schrieb:

    man könnte den BackgroundWorker auch ganz weglassen
    wohl wahr!

    IMO ist BW Schrott aus Zeiten, als es noch keine Generica gab. Ich hab mal so eine Verbesserung geproggt: AsyncWorker - CodeProject

    Aber inzwischen kann man auch mit Await/Async ganz hübsche Sachen machen - nur ich nicht, weil nur vb2010.

    Rainman schrieb:

    der dann mit dem Holzhammer thread.Abort() terminiert werden kann.
    Klingt wie in Post #2 beschrieben.
    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 habe den BackgroundWorker entsorgt und durch einen Thread ersetzt, wie in #2 angeregt.
    Die BackgroundWorker-Überbleibsel sieht man noch an den Prozedurnamen :)
    Der Haupt-Thread wird von einem zweiten WatchDog-Thread überwacht, der den ersten ggf. abschießt.
    Eigentlich ganz simpel, wenn auch evtl. der WatchDog unnötig oft gecancelt wird.
    Sollte man das anders lösen oder ist die Abort()-Geschichte dem Laufzeitsystem eher egal?

    Quellcode

    1. ' Das Formular benötigt zwei Buttons und eine Textbox.
    2. Dim t_Work As Threading.Thread
    3. Dim t_WatchDog As Threading.Thread
    4. ' Den überwachten Thread und den WatchDog starten.
    5. Private Sub Start2_Click(sender As Object, e As EventArgs) Handles Start2.Click
    6. Start2.Enabled = False
    7. t_Work = New Threading.Thread(AddressOf t_DoWork)
    8. t_Work.Start() ' Soll nach max. 5s fertig sein.
    9. t_WatchDog = New Threading.Thread(AddressOf t_timer)
    10. t_WatchDog.Start() ' Überwachung der Laufzeit starten.
    11. End Sub
    12. ' WatchDog
    13. Sub t_timer()
    14. Sleep(7000) ' :: hier z.B. 2000 eintragen um den Abbruch durchzuführen.
    15. t_Work.Abort() ' den überwachten Thread abschießen.
    16. Invoke(Sub() Abbruchmeldung())
    17. End Sub
    18. ' Den überwachten Thread manuell abschießen.
    19. Private Sub Cancel2_Click(sender As Object, e As EventArgs) Handles Cancel2.Click
    20. If t_Work IsNot Nothing AndAlso t_Work.IsAlive Then
    21. t_Work.Abort() ' den überwachten Thread abschießen.
    22. t_WatchDog.Abort() ' den WatchDog abschießen.
    23. Abbruchmeldung()
    24. End If
    25. End Sub
    26. Private Sub t_DoWork()
    27. For i = 1 To 10
    28. ' hier den durch Aufhängen bedrohten Job aufrufen.
    29. Invoke(Sub() t_ProgressChanged(i))
    30. Sleep(500)
    31. Next
    32. t_WatchDog.Abort() ' den WatchDog abschießen, weil nun nicht mehr benötigt.
    33. Invoke(Sub() t_RunWorkerCompleted())
    34. End Sub
    35. Private Sub t_ProgressChanged(i As Integer)
    36. Wert2.Text = i.ToString
    37. End Sub
    38. Private Sub t_RunWorkerCompleted()
    39. Wert2.Text &= " Fertig"
    40. Start2.Enabled = True
    41. End Sub
    42. Private Sub Abbruchmeldung()
    43. Wert2.Text &= " Abbruch"
    44. Start2.Enabled = True
    45. End Sub


    PS: die Kombination aus BackgroundWorker und WatchDog habe ich nicht hinbekommen.
    Braucht man aber auch nicht mehr, Threads sind eh besser.
    An manchen Tagen gibt es zu allem Überfluss auch noch Ärger!

    Rainman schrieb:

    ist die Abort()-Geschichte dem Laufzeitsystem eher egal?
    "Normalerweise" sollte sich ein Thread selbst beenden, wenn seine Arbeit getan ist, er verlässt die Thread-Prozedur und feddich.
    Wenn in einem Thread eine (Endlos-) Schleife drin ist, kann man von außen ein Flag setzen, dass die Schleife verlassen und damit der Thread beendet wird.
    Ist dies nicht möglich, muss man halt zum Holzhammer greifen.
    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!