Problem mit Event und verschiedenen Task

  • VB.NET
  • .NET (FX) 4.5–4.8

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

    Problem mit Event und verschiedenen Task

    Hallo und schönen guten Abend

    Ich habe hier ein Problem, wovon ich nicht weiß ob es ein Timing Problem ist, oder etwas anderes.
    Man kann folgendes im Programm anstoßen:
    1.) Daten kopieren
    2.) Daten zippen
    3.) Daten kopieren und zippen gleichzeitig.


    Die Funktionen des kopieren und zippen, dabei ist alles OK.
    Probleme macht das Anzeigen und Reseten auf dem Form. Wenn beide Task laufen ist es ok. Bei den Einzelläufen gibt es das Problem des nicht anzeigens.

    Wenn beide Task laufen Debug:

    XML-Quellcode

    1. ZippAsync gestartet
    2. KopiereAsync gestartet
    3. KopiereAsync beendet
    4. KopiereAsync success:True
    5. InClass-First: 1
    6. ZippAsync beendet
    7. ZippAsync success:True
    8. InClass-First: 0
    9. InClassElse: 0
    10. MeldungsID: 0
    11. CompletedOperationType: 0
    12. Bedingung 2 erfüllt

    Wenn nur kopieren läuft kommt dieser Debug:

    XML-Quellcode

    1. KopiereAsync gestartet
    2. KopiereAsync beendet
    3. KopiereAsync success:True
    4. InClass-First: 1

    Wenn nur zippen läuft kommt dieser Debug:

    XML-Quellcode

    1. ZippAsync gestartet
    2. Der Thread 0xe70 hat mit Code 259 (0x103) geendet.
    3. ZippAsync beendet
    4. ZippAsync success:True
    5. InClass-First: 0


    Der relevante Code:
    Spoiler anzeigen

    Ausug aus der Class:

    VB.NET-Quellcode

    1. Friend Event MeldungsID(MeldungID As Integer, Typ As Integer)
    2. Friend CompletedOperations As Integer
    3. Friend CompletedOperationType As Integer = -1
    4. Friend Async Sub ZippAsync()
    5. Debug.WriteLine("ZippAsync gestartet")
    6. Dim success As Boolean = Await Threading.Tasks.Task.Run(Function() CallZip())
    7. Debug.WriteLine("ZippAsync beendet")
    8. If success Then
    9. Debug.WriteLine("ZippAsync success:" & success)
    10. OperationCompleted(0)
    11. End If
    12. End Sub
    13. Friend Async Sub KopiereAsync()
    14. Debug.WriteLine("KopiereAsync gestartet")
    15. Dim success As Boolean = Await Threading.Tasks.Task.Run(Function() CallCopy())
    16. Debug.WriteLine("KopiereAsync beendet")
    17. If success Then
    18. Debug.WriteLine("KopiereAsync success:" & success)
    19. OperationCompleted(1)
    20. End If
    21. End Sub
    22. Friend Sub OperationCompleted(operationType As Integer)
    23. Debug.WriteLine("InClass-First: " & operationType)
    24. If CompletedOperationType = -1 Then
    25. CompletedOperationType = operationType
    26. Else
    27. If CompletedOperationType = operationType Then
    28. CompletedOperationType = -1
    29. Interlocked.Exchange(CompletedOperations, 0)
    30. Debug.WriteLine("InClassIf: " & operationType)
    31. RaiseEvent MeldungsID(0, operationType)
    32. Else
    33. CompletedOperationType = -1
    34. Interlocked.Exchange(CompletedOperations, 0)
    35. Debug.WriteLine("InClassElse: " & operationType)
    36. RaiseEvent MeldungsID(0, operationType)
    37. End If
    38. End If
    39. End Sub

    Auszug aus dem Form:

    VB.NET-Quellcode

    1. Private Sub Mitteilungen(ByVal var As Integer, typ As Integer) Handles copyzip.MeldungsID
    2. Debug.WriteLine("MeldungsID: " & var & Environment.NewLine & "CompletedOperationType: " & typ)
    3. If var = 0 AndAlso typ = 1 Or var = 1 AndAlso typ = 0 Then
    4. Debug.WriteLine("Bedingung 1 erfüllt")
    5. ResetControls()
    6. RestProgrssbar()
    7. logger.AddLogEntry(EventExceptionRecorder.LogLevel.Success, "Single-Task abgeschlossen.")
    8. 'Der Zweig funktioniert wenn Copy&Zip gleichzeitig laufen
    9. ElseIf var = 0 AndAlso typ = 0 Then
    10. Debug.WriteLine("Bedingung 2 erfüllt")
    11. ResetControls()
    12. RestProgrssbar()
    13. logger.AddLogEntry(EventExceptionRecorder.LogLevel.Success, "Copy und Zip-Task abgeschlossen.")
    14. End If
    15. End Sub

    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    Amelie schrieb:

    Daten kopieren und zippen gleichzeitig.
    Bedenke bei Deinem Problem, dass es nur einen Festplattenzugriff gleichzeitig geben kann.
    Wenn Du also n Dateien nacheinender zippst/kopierst, dauert das deutlich weniger lange, als wenn Du dies parallel tust.
    ====
    Dies gilt insbesondere für Schreibvorgänge.
    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!

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „RodFromGermany“ ()

    @RodFromGermany und @Haudruferzappeltnoch

    Das Kopieren und Zippen ist ja nicht das Problem, sondern nur das anzeigen bzw Resten auf dem Form.
    Kopieren und zippen wird eh zu 90% auf 2 Festpaltten geschehen und ob das nun 20 oder 30 Sekunden dauert ist auch egal.

    Es geht ausschließlich darum, das hier nicht richtig gearbeitet wird bzw die falschen Infos aus der Klasse kommen.

    VB.NET-Quellcode

    1. Private Sub Mitteilungen(ByVal var As Integer, typ As Integer) Handles copyzip.MeldungsID
    2. Debug.WriteLine("MeldungsID: " & var & Environment.NewLine & "CompletedOperationType: " & typ)
    3. If var = 0 AndAlso typ = 1 Or var = 1 AndAlso typ = 0 Then
    4. Debug.WriteLine("Bedingung 1 erfüllt")
    5. ResetControls()....
    6. End Sub



    EDIT 19:40 Uhr

    @RodFromGermany
    ​Wenn Du also n Dateien nacheinender


    Wenn ich das gleichzeitige nicht parallel sondern nacheinander ablaufen lassen würde, bräuchte ich dabei AUCH nur 1 Mal Restten :?: :rolleyes:
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Amelie“ ()

    mir scheint, Mitteilungen wird in einen NebenThread gefeuert, und damit hast du Threadübergreifende Aufrufe an diverse Controls.
    Eiglich müssteste dafür eine InvalidOperationException geben.
    Prüf mal, ob du die nicht deaktiviert hast, mit CheckForInvalidThreadCalls=False. Vielleicht heisst CheckForInvalidThreadCalls auch anders, so ähnlich - weiss ich nicht, ich mache das nie.

    Jedenfalls gehen Threadübergreifende Calls gelegentlich daneben, und ist schwer zu debuggen.
    @ErfinderDesRades
    In der Tat hat mein "Logger" das mal aufgefangen:
    ​[Failure] 01.10.2023 - 19:57 Ungültiger threadübergreifender Vorgang: Der Zugriff auf das Steuerelement pbProgressbar erfolgte von einem anderen Thread als dem Thread, für den es erstellt wurde.
    Was mir das Studio aber NICHT ausgab!

    @Haudruferzappeltnoch
    Was möchtest du mir sagen?

    @RodFromGermany
    Das hier wird ausgeführt:
    ​ Private Sub RestProgrssbar() Me.Invoke(Sub() pbProgressbar.Visible = False) End Sub


    Im Moment teste ich diese Kombinationen durch: Das "Dim Success" nehme ich noch raus.
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Friend Async Sub ZippAsync()
    2. Debug.WriteLine("ZippAsync gestartet")
    3. Dim success As Boolean = Await Threading.Tasks.Task.Run(Function() CallZip())
    4. Debug.WriteLine("ZippAsync beendet")
    5. If success Then
    6. Debug.WriteLine("ZippAsync success:" & success)
    7. OperationCompleted(1) ' Geändert zu 1 für ZippAsync
    8. End If
    9. End Sub
    10. Friend Async Sub KopiereAsync()
    11. Debug.WriteLine("KopiereAsync gestartet")
    12. Dim success As Boolean = Await Threading.Tasks.Task.Run(Function() CallCopy())
    13. Debug.WriteLine("KopiereAsync beendet")
    14. If success Then
    15. Debug.WriteLine("KopiereAsync success:" & success)
    16. OperationCompleted(1) ' Geändert zu 1 für KopiereAsync
    17. End If
    18. End Sub
    19. Friend Async Sub KopiereZipAsync()
    20. Debug.WriteLine("KopiereAsync gestartet")
    21. Await Threading.Tasks.Task.Run(Function() CallCopy())
    22. Debug.WriteLine("KopiereAsync beendet")
    23. Debug.WriteLine("KopiereAsync gestartet")
    24. Await Threading.Tasks.Task.Run(Function() CallZip())
    25. Debug.WriteLine("KopiereAsync beendet")
    26. OperationCompleted(2) ' Geändert zu 2 für KopiereZipAsync
    27. End Sub


    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    Amelie schrieb:

    @ErfinderDesRades
    In der Tat hat mein "Logger" das mal aufgefangen:
    [Failure] 01.10.2023 - 19:57 Ungültiger threadübergreifender Vorgang: Der Zugriff auf das Steuerelement pbProgressbar erfolgte von einem anderen Thread als dem Thread, für den es erstellt wurde.
    Was mir das Studio aber NICHT ausgab!
    tja, scheints ist da iwo ein TryCatch.
    wird die Exception weggeCatcht, kann VS die nichtmehr ausgeben.

    Amelie schrieb:

    Das hier wird ausgeführt:

    RodFromGermany schrieb:

    Was passiert da?
    Falsche Antwort.
    Nicht der Aufruf, sondern der Inhalt war gefragt. ;)
    @ErfinderDesRades Exceptions in einem Thread ist so ne Sache, da muss man sich von außen nach innen rantasten und natürlich die Exception-Info richtig auswerten.
    Da hapert es ggf. bei Amelie.
    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!
    Moin moin

    Ich habe nun den "vorläufigen" Code etwas umgeschrieben und bisher klappt alles im Testlauf.
    Ich versuche noch den Code zu verschlanken... Tips dazu nehme ich gerne an. :)

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private errorHdd As String
    2. Private Function IsDriveReady(ByVal HDD As String) As Boolean
    3. Dim driveInfo As System.IO.DriveInfo = Nothing
    4. If Not String.IsNullOrEmpty(HDD) AndAlso System.IO.Directory.Exists(HDD) Then
    5. driveInfo = New System.IO.DriveInfo(HDD)
    6. End If
    7. If driveInfo IsNot Nothing AndAlso driveInfo.IsReady Then
    8. Return True
    9. Else
    10. errorHdd = HDD
    11. RaiseEvent MeldungsID(5)
    12. Return False
    13. End If
    14. End Function
    15. Friend Sub Threadsstarten(SelectedCopytype As Integer)
    16. Select Case SelectedCopytype
    17. Case Is = 0
    18. If IsDriveReady(propertyinfo.SourcePath) AndAlso IsDriveReady(propertyinfo.TargetPathCopy) Then
    19. KopiereAsync()
    20. Else
    21. logger.AddLogEntry(EventExceptionRecorder.LogLevel.Failure, "Das Laufwerk " & errorHdd & " meldet einen Fehler.")
    22. End If
    23. Case Is = 1
    24. If IsDriveReady(propertyinfo.SourcePath) AndAlso IsDriveReady(propertyinfo.TargetPathZip) Then
    25. ZippAsync()
    26. Else
    27. logger.AddLogEntry(EventExceptionRecorder.LogLevel.Failure, "Das Laufwerk " & errorHdd & " meldet einen Fehler.")
    28. End If
    29. Case Is = 2
    30. If IsDriveReady(propertyinfo.SourcePath) AndAlso IsDriveReady(propertyinfo.TargetPathCopy) AndAlso IsDriveReady(propertyinfo.TargetPathZip) Then
    31. KopiereZipAsync()
    32. Else
    33. logger.AddLogEntry(EventExceptionRecorder.LogLevel.Failure, "Das Laufwerk " & errorHdd & " meldet einen Fehler.")
    34. End If
    35. End Select
    36. End Sub
    37. Private Async Sub KopiereAsync()
    38. Debug.WriteLine("KopiereAsync gestartet")
    39. Await Threading.Tasks.Task.Run(Function() CallCopy())
    40. Debug.WriteLine("KopiereAsync beendet")
    41. logger.AddLogEntry(EventExceptionRecorder.LogLevel.Debug, "Debug: Single-Task 'Kopieren'abgeschlossen.")
    42. RaiseEvent MeldungsID(0)
    43. End Sub
    44. Private Async Sub ZippAsync()
    45. Debug.WriteLine("ZippAsync gestartet")
    46. Await Threading.Tasks.Task.Run(Function() CallZip())
    47. Debug.WriteLine("ZippAsync beendet")
    48. logger.AddLogEntry(EventExceptionRecorder.LogLevel.Debug, "Debug: Single-Task 'Zippen'abgeschlossen.")
    49. RaiseEvent MeldungsID(1)
    50. End Sub
    51. Private Async Sub KopiereZipAsync()
    52. Debug.WriteLine("KopiereAsync gestartet")
    53. Await Threading.Tasks.Task.Run(Function() CallCopy())
    54. Debug.WriteLine("KopiereAsync beendet")
    55. Debug.WriteLine("ZippAsync gestartet")
    56. Await Threading.Tasks.Task.Run(Function() CallZip())
    57. Debug.WriteLine("ZippAsync beendet")
    58. logger.AddLogEntry(EventExceptionRecorder.LogLevel.Debug, "Debug: Double-Task 'Kopieren und Zippen'abgeschlossen.")
    59. RaiseEvent MeldungsID(2)
    60. End Sub


    VB.NET-Quellcode

    1. Private Sub Mitteilungen(ByVal var As Integer) Handles copyzip.MeldungsID
    2. Debug.WriteLine("MeldungsID: " & var)
    3. If var = 0 Then
    4. Debug.WriteLine("Bedingung 0 erfüllt")
    5. ResetControls()
    6. RestProgrssbar()
    7. logger.AddLogEntry(EventExceptionRecorder.LogLevel.Success, "Single-Task 'Kopieren' abgeschlossen.")
    8. ElseIf var = 1 Then
    9. Debug.WriteLine("Bedingung 1 erfüllt")
    10. ResetControls()
    11. RestProgrssbar()
    12. logger.AddLogEntry(EventExceptionRecorder.LogLevel.Success, "Single-Task 'Zippen' abgeschlossen.")
    13. ElseIf var = 2 Then
    14. Debug.WriteLine("Bedingung 2 erfüllt")
    15. ResetControls()
    16. RestProgrssbar()
    17. logger.AddLogEntry(EventExceptionRecorder.LogLevel.Success, "Double-Task 'Kopieren und Zippen'abgeschlossen.")
    18. ElseIf var = 5 Then
    19. Debug.WriteLine("Bedingung 5 erfüllt") ' Wenn Fehler auftreten.
    20. ResetControls()
    21. RestProgrssbar()
    22. End If
    23. End Sub



    @RodFromGermany
    ​Exception-Info richtig auswerten

    Ja da tut ich mich noch oft schwer mit. :(
    Und in einigen Testläufen habe ich festgestellt, das es subjektiv kaum einen Geschwindigkeitsunterschied macht ob ich die alte oder neue Version des "Copy & Zip" mache. Zumal das Source und das TargetZip immer USB-Geräte sind.


    @ErfinderDesRades
    Ich versuche so wenig wie möglich Try/Catch zu verwenden. Ist nicht einfach, wenn man das "immer" verwendet hat.
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:
    @Amelie Gib Deiner Sub Mitteilungen() keinen Integer als Parameter, sondern einen Enum.
    Und gib den Enum-Items klingende Namen, da liest sich Dein Code wesentlich leichter und Du musst nicht überprüfen, ob ein Integer-Wert schon in Benutzung ist.
    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!
    @RodFromGermany

    Habe das nun so umgesetzt. :thumbsup:

    VB.NET-Quellcode

    1. Public Class CopyZip
    2. Friend Enum Meldung
    3. Copy
    4. Zip
    5. Both
    6. Failure
    7. End Enum
    8. Friend Event MeldungsID(MeldungID As Meldung)
    9. Private Async Sub KopiereAsync()
    10. Debug.WriteLine("KopiereAsync gestartet")
    11. Await Threading.Tasks.Task.Run(Function() CallCopy())
    12. Debug.WriteLine("KopiereAsync beendet")
    13. logger.AddLogEntry(EventExceptionRecorder.LogLevel.Debug, "Debug: Single-Task 'Kopieren'abgeschlossen.")
    14. RaiseEvent MeldungsID(Meldung.Copy)
    15. End Sub


    Was noch zuweilen Probleme macht, ist die Prüfung ob ein Laufwerk vorhanden / bereit ist. Hier verhällt sich mein Code gerade merkwürdig. Mal geht es mal nicht.... ?(
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    Amelie schrieb:

    Was noch zuweilen Probleme macht, ist die Prüfung ob ein Laufwerk vorhanden / bereit ist.
    Mit welchen Parametern rufst Du denn diese Funktion auf?
    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!
    @RodFromGermany
    Im Moment spinnt alles. ;( Deswegen mal auf einfachste reduziert.

    Laufwerke vorhanden! Die Funktion meldet einen Fehler lässt aber die MSGBox nicht aufpoppen. ?(
    Habe ich ein Brett vorm Kopf??? ;(

    VB.NET-Quellcode

    1. Friend Function IsDriveReady(ByVal HDD As String) As Boolean
    2. Try
    3. Return Directory.Exists(HDD)
    4. Catch ex As Exception
    5. MessageBox.Show(ex.Message) ' Die popt nicht auf!!!
    6. Return False
    7. End Try
    8. End Function
    9. Friend Sub Threadsstarten(SelectedCopytype As Integer)
    10. Select Case SelectedCopytype
    11. Case Is = 0
    12. If IsDriveReady(propertyinfo.SourcePath) AndAlso IsDriveReady(propertyinfo.TargetPathCopy) Then
    13. KopiereAsync()
    14. Else
    15. logger.AddLogEntry(EventExceptionRecorder.LogLevel.Failure, "Das Laufwerk " & errorHdd & " meldet einen Fehler.") 'Hier wird aber ein Fehler gemeldet
    16. End If
    17. End Select
    18. End Sub
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    Amelie schrieb:

    VB.NET-Quellcode

    1. ' Die popt nicht auf!!!
    Ich behaupte mal, dass die Funktion Directory.Exists(..) keine Exception wirft.
    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!
    was auch in der Doku steht:

    Microsoft-Doku schrieb:

    Gibt zurück
    true, wenn sich path auf ein vorhandenes Verzeichnis bezieht; false, wenn ein Verzeichnis nicht vorhanden ist, oder wenn beim Versuch festzustellen, ob ein angegebenes Verzeichnis vorhanden ist, ein Fehler auftritt.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Amelie schrieb:

    Ich versuche so wenig wie möglich Try/Catch zu verwenden. Ist nicht einfach, wenn man das "immer" verwendet hat.
    Hihi!
    Tipp: Lass es einfach.
    Das ist durchaus ganz einfach: Einfach es unterlassen.

    Und - wurde schon gesagt - Doku lesen. Einfacher als mit dem ObjectBrowser gehts einfach nicht. VisualStudio richtig nutzen (Google ist nicht deine Mami)

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Konnte das Problem nun eingrenzen und zumindest für den Moment beheben.
    Habe auch nochmal das Thema hier mit dem Try/Catch gelesen. Ist nicht leicht diese Blöcke wegzulassen wenn man sich so daran "gewöhnt" hat, auch wenn es, was ich mittlerweile weiß eine eher schlechte Angewohnheit ist.
    So nach dem Motto: "Fehler wegklicken nur damit das Programm nicht abstürzt"
    Muss noch herausfinden, wann die "Sinnvoll" sein können und wann eben nicht.
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh: