Schnellerer Datei Check

  • VB.NET
  • .NET 4.5

Es gibt 25 Antworten in diesem Thema. Der letzte Beitrag () ist von Kasi.

    Schnellerer Datei Check

    Hallo, ich habe ein Kleines Problem. und zwar ich habe einen Ordner der mit dem Code (unten) überprüft wird. das ganze dauert nur blöderweise ca. 25min (Für 1600 Dateien)
    nun ist die Frage wie das ganze Schneller laufen würde?
    - Code Läuft im Thread

    VB.NET-Quellcode

    1. Dim di As New System.IO.DirectoryInfo(My.Settings.modpath)
    2. For Each items As System.IO.FileInfo In di.GetFiles("*.*", System.IO.SearchOption.AllDirectories)
    3. FileCount = FileCount + 1
    4. Dim found As Boolean = IsFileFound(MD5FileHash(items.FullName).ToLower)
    5. Dim file As String = IO.Path.GetFileName(items.FullName)
    6. If found = False Then
    7. My.Computer.FileSystem.DeleteFile(items.FullName)
    8. End If
    9. Next


    Danke im Voraus.

    Was macht das?

    IsFileFound(MD5FileHash(items.FullName).ToLower)

    arbeite mal mit dem FileInfo objekt direkt:

    VB.NET-Quellcode

    1. Dim di As New System.IO.DirectoryInfo(My.Settings.modpath)
    2. For Each datei As System.IO.FileInfo In di.GetFiles("*.*", System.IO.SearchOption.AllDirectories)
    3. FileCount = FileCount + 1
    4. Dim found As Boolean = IsFileFound(MD5FileHash(datei.FullName).ToLower)
    5. If found = False Then
    6. datei.delete
    7. End If
    8. Next

    "Gib einem Mann einen Fisch und du ernährst ihn für einen Tag. Lehre einen Mann zu fischen und du ernährst ihn für sein Leben."

    Wie debugge ich richtig? => Debuggen, Fehler finden und beseitigen
    Wie man VisualStudio nutzt? => VisualStudio richtig nutzen
    Das Vergleicht den MD5hash beider Dateien und wenn beide den Gleichen Hash haben wird Fortgesetzt.

    EDIT: Das Löschen einer Datei Dauert nicht mal lange @mrMo . das was Lange Dauert ist die Überprüfung.

    Ich lass mir ja im Label den Count anzeigen. bei welcher Datei er ist.

    VB.NET-Quellcode

    1. Dim di As New System.IO.DirectoryInfo(My.Settings.modpath)
    2. For Each datei As System.IO.FileInfo In di.GetFiles("*.*", System.IO.SearchOption.AllDirectories)
    3. FileCount = FileCount + 1
    4. Label9.Text = "Prüfe Dateien: " & FileCount
    5. Dim found As Boolean = IsFileFound(MD5FileHash(datei.FullName).ToLower)
    6. If found = False Then
    7. MessageBox.Show("Datei Gelöscht")
    8. ' datei.Delete()
    9. End If
    10. Next


    und das Dauert bei 1600 Dateien eben sehr Lange... (Ca. 20min)
    1 Sek = 1 Datei (Ca.)




    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „xX-Nick-Xx“ ()

    xX-Nick-Xx schrieb:

    Code Läuft im Thread
    Ja, im Mainthread, wohl kaum aber in einem separaten Thread. Weil von dort aus kannst du nicht ohne weiteres auf Controls zugreifen, was du ja aber machst um den Wert von FileCount anzuzeigen.

    Lass mal die IsFileFound Methode weg und schau wie schnell das ganze dann läuft. Denke das ist dein Zeitfresser.
    "Gib einem Mann einen Fisch und du ernährst ihn für einen Tag. Lehre einen Mann zu fischen und du ernährst ihn für sein Leben."

    Wie debugge ich richtig? => Debuggen, Fehler finden und beseitigen
    Wie man VisualStudio nutzt? => VisualStudio richtig nutzen
    @mrMo ohne diese Funktion wird aber leider nicht das gemacht was es soll :P

    OPTION STRICT = ON
    MD5:

    VB.NET-Quellcode

    1. Public Function MD5FileHash(ByVal sFile As String) As String
    2. Dim MD5 As New MD5CryptoServiceProvider
    3. Dim Hash As Byte()
    4. Dim Result As String = ""
    5. Dim Tmp As String = ""
    6. Dim FN As New FileStream(sFile, FileMode.Open, FileAccess.Read, FileShare.Read, 8192)
    7. MD5.ComputeHash(FN)
    8. FN.Close()
    9. Hash = MD5.Hash
    10. For i As Integer = 0 To Hash.Length - 1
    11. Tmp = Hex(Hash(i))
    12. If Len(Tmp) = 1 Then Tmp = "0" & Tmp
    13. Result += Tmp
    14. Next
    15. Return Result
    16. End Function


    IsFileFound:

    VB.NET-Quellcode

    1. Public Function IsFileFound(ByVal hash As String) As Boolean
    2. Dim content As String = SendLink(ServerAdresse & "ID3")
    3. Dim json As JObject = JObject.Parse(content)
    4. Dim Index As Integer = 0
    5. While Index < (Convert.ToInt32(json.SelectToken("count")))
    6. If json.SelectToken(Index & ".hash") IsNot Nothing Then
    7. If hash.ToLower = CType(json.SelectToken(Index & ".hash"), String) Then
    8. Return True
    9. End If
    10. End If
    11. Index += 1
    12. End While
    13. Return False
    14. End Function


    PS: Läuft im Seperaten Thread

    xX-Nick-Xx schrieb:

    Nein. die JSON Abfrage wird 1. Durchgeführt. (eig. )


    SendLink wird bei jedem Schleifen Durchlauf aufgerufen... also?

    Wo genau ist denn deine Methode in der der Thread gestartet wird? Davon ist nix im Code zu sehen, du behauptest das immer nur....

    xX-Nick-Xx schrieb:

    @mrMo ohne diese Funktion wird aber leider nicht das gemacht was es soll :P
    ja das ist mir schon klar. Es geht darum heraus zu finden wo die Zeit flöten geht. Da hilft es einzelne Elemente im Code auszukommentieren und zu schauen ob es dann schneller wird. Falls ja, hat man einen Zeitfresser gefunden und kann dort weiter forschen.

    "Gib einem Mann einen Fisch und du ernährst ihn für einen Tag. Lehre einen Mann zu fischen und du ernährst ihn für sein Leben."

    Wie debugge ich richtig? => Debuggen, Fehler finden und beseitigen
    Wie man VisualStudio nutzt? => VisualStudio richtig nutzen

    mrMo schrieb:

    ja das ist mir schon klar. Es geht darum heraus zu finden wo die Zeit flöten geht. Da hilft es einzelne Elemente im Code auszukommentieren und zu schauen ob es dann schneller wird. Falls ja, hat man einen Zeitfresser gefunden und kann dort weiter forschen.


    Hab mal

    VB.NET-Quellcode

    1. ​Dim found As Boolean = IsFileFound(MD5FileHash(datei.FullName).ToLower)
    auskommentiert.
    nun ist die Überprüfung nach ein paar Sekunden fertig.

    Ja ok also ist dort der Zeitfresser. Jetzt ermittel mal, wie oft SendLink aufgerufen wird. Denke pro Datei einmal. Da hier so wie es aussieht immer das gleiche passiert, versuche den Aufruf außerhalb der schleife zu machen und das Ergebnis entsprechend in der Schleife zu verarbeiten.
    "Gib einem Mann einen Fisch und du ernährst ihn für einen Tag. Lehre einen Mann zu fischen und du ernährst ihn für sein Leben."

    Wie debugge ich richtig? => Debuggen, Fehler finden und beseitigen
    Wie man VisualStudio nutzt? => VisualStudio richtig nutzen
    Danke.
    Also ich habe es Geschafft das der Count schneller läuft.
    Das Problem was noch besteht ist das sich die Form Kurzzeitig (sehr oft Kurzzeitig) einfrieren tut. ich Denke mal das "IsFileFound" auch noch im Thread laufen sollte.
    Nur wie ich das am Besten machen soll ohne den Thread dauerhaft zu Starten weiß ich noch nicht.
    Bzw. mit den Parametern übergeben....

    xX-Nick-Xx schrieb:

    VB.NET-Quellcode

    1. Hash = MD5.Hash
    2. For i As Integer = 0 To Hash.Length - 1
    3. Tmp = Hex(Hash(i))
    4. If Len(Tmp) = 1 Then Tmp = "0" & Tmp
    5. Result += Tmp
    6. Next
    machst Du

    VB.NET-Quellcode

    1. Hash = MD5.Hash
    2. For i As Integer = 0 To Hash.Length - 1
    3. Result += Hash(i).ToString("X2")
    4. Next
    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!
    @xX-Nick-Xx
    Was hast du nun gemacht damit die Schleife schneller läuft?

    Schmeiß dein ganzes Thread Zeug weg und nutze async. -> docs.microsoft.com/de-de/dotne…ing-guide/concepts/async/

    VB.NET-Quellcode

    1. Private async Sub Button8_Click(sender As Object, e As EventArgs) Handles Button8.Click
    2. Await Task.Run(AddressOf CheckFiles)
    3. End Sub
    Alles was dann innerhalb von CheckFiles passiert, passiert asynchron (separater Thread) und blockiert deine GUI nicht.

    Sofern innerhalb von CheckFiles auf Controls zugegriffen werden muss, geht dies so:

    VB.NET-Quellcode

    1. BeginInvoke(Sub() Label9.Text = "Prüfe Dateien: " & FileCount)
    "Gib einem Mann einen Fisch und du ernährst ihn für einen Tag. Lehre einen Mann zu fischen und du ernährst ihn für sein Leben."

    Wie debugge ich richtig? => Debuggen, Fehler finden und beseitigen
    Wie man VisualStudio nutzt? => VisualStudio richtig nutzen
    In Post#10 kommst Du mit dem Threadaufruf neuerthread3 = New System.Threading.Thread(AddressOf CheckFiles). Die nebenläufige Prozedur CheckFiles ist aber bis jetzt nirgends erwähnt.

    xX-Nick-Xx schrieb:

    ich Denke mal das "IsFileFound" auch noch im Thread laufen sollte.
    Das impliziert, dass der Code aus Post#1, in dem IsFileFound auftaucht, nicht der Code von CheckFiles ist. Wieviele Puzzleteile fehlen noch, bis endlich ein Gesamtbild sichtbar wird? Erst dann kann man auch sinnvoll weiterhelfen.

    @mrMo: Kleiner Verbesserungsvorschlag, weil ja an diese ominöse CheckFiles noch ein Parameter übergeben werden muss:

    VB.NET-Quellcode

    1. Private Async Sub Button8_Click(sender As Object, e As EventArgs) Handles Button8.Click
    2. Await Task.Run(Sub() CheckFiles(My.Settings.modpath))
    3. End Sub

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Häufig von mir verwendete Abkürzungen: CEs = control elements (Labels, Buttons, DGVs, ...) und tDS (typisiertes DataSet)
    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht in den Spekulatiusmodus gehen.

    VaporiZed schrieb:

    Die nebenläufige Prozedur CheckFiles ist aber bis jetzt nirgends erwähnt.
    ja richtig ich habe bisher lediglich angenommen das CheckFiles den Code aus Post #1 beinhaltet. Wissen tu ich das aber nicht, da @xX-Nick-Xx (achtung Kritik) immer teile von Code weg lässt wo er meint das die nicht wichtig wären und wir dann immer nachfragen müssen ...
    "Gib einem Mann einen Fisch und du ernährst ihn für einen Tag. Lehre einen Mann zu fischen und du ernährst ihn für sein Leben."

    Wie debugge ich richtig? => Debuggen, Fehler finden und beseitigen
    Wie man VisualStudio nutzt? => VisualStudio richtig nutzen
    CheckFiles wurd zur Hälfte schon erwähnt. Da ich den Restlichen teil für nicht nötig hielt habe ich ihn weg gelassen...

    Habe die Änderungen gemacht, nun Hängt sich die Form beim Bewegen auf und der Taskmanager gibt "Keine Rückmeldung" Zurück.

    CheckFiles:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Sub CheckFiles(ByVal folder As String)
    2. Try
    3. PlsWait.Enabled = True
    4. Dim CountFiles As Integer = My.Computer.FileSystem.GetFiles(My.Settings.modpath, FileIO.SearchOption.SearchAllSubDirectories, "*.*").Count
    5. content = SendLink(ServerAdresse & "ID3")
    6. json = JObject.Parse(content)
    7. Dim ServerPath As String = CType(Convert.ToInt32(json.SelectToken("count")), String)
    8. If CountFiles = 0 Then
    9. BeginInvoke(Sub() Label9.Text = "Keine Dateien gefunden...")
    10. PlsWait.Enabled = False
    11. Label13.Visible = False
    12. Button2.Enabled = True
    13. Status = 3
    14. BeginInvoke(Sub() Label9.Text = "Willkommen Zurück " & Environment.UserName)
    15. UpdateMod = "1"
    16. ElseIf CountFiles = CInt(ServerPath) Then
    17. BeginInvoke(Sub() Label9.Text = "Daten Aktuell")
    18. Sleep(4000)
    19. PlsWait.Enabled = False
    20. Label13.Visible = False
    21. Button2.Enabled = True
    22. Status = 3
    23. BeginInvoke(Sub() Label9.Text = "Willkommen Zurück " & Environment.UserName)
    24. ElseIf CountFiles > 0 Then
    25. BeginInvoke(Sub() Label9.Text = "Daten müssen Überprüft werden..." & vbNewLine & "Das kann einen Augenblick Dauern...")
    26. Sleep(4000)
    27. Dim di As New System.IO.DirectoryInfo(My.Settings.modpath)
    28. For Each datei As System.IO.FileInfo In di.GetFiles("*.*", System.IO.SearchOption.AllDirectories)
    29. FileCount = FileCount + 1
    30. BeginInvoke(Sub() Label9.Text = "Prüfe Dateien: " & FileCount)
    31. Dim found As Boolean = IsFileFound(MD5FileHash(datei.FullName).ToLower)
    32. If found = False Then
    33. ' datei.Delete()
    34. End If
    35. Next
    36. Else
    37. End If
    38. If CountFiles = FileCount Then
    39. PlsWait.Enabled = False
    40. Label13.Visible = False
    41. BeginInvoke(Sub() Label9.Text = "Es wurden " & CountDel & " Elemente gelöscht")
    42. Button2.Enabled = True
    43. Status = 3
    44. Else
    45. ' Label9.Text = "Prüfe Dateien: " & FileCount & "/" & CountFiles
    46. End If
    47. Catch ex As Exception
    48. MsgBox(ex.Message & " - " & ex.StackTrace)
    49. End Try
    50. End Sub

    Irgendwie habe ich das Gefühl, dass der Aufruf von CheckFiles nicht korrekt ist oder dass Du irgendwo CheckForIllegalCrossThreadCalls = False gemacht hast. Denn Aufrufe wie

    VB.NET-Quellcode

    1. PlsWait.Enabled = False
    2. Label13.Visible = False
    3. Button2.Enabled = True

    würden immer in einem nebenläufigen Thread crashen. Da dies nicht passiert, zeigt mir, dass da was nicht stimmt.
    Wie ist Dein Aufruf von CheckFiles? Bitte Screenshot oder Copy&Paste.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Häufig von mir verwendete Abkürzungen: CEs = control elements (Labels, Buttons, DGVs, ...) und tDS (typisiertes DataSet)
    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht in den Spekulatiusmodus gehen.