FileInfo.Refresh und Exists sind irgendwie lahm

  • VB.NET
  • .NET 5–6

Es gibt 4 Antworten in diesem Thema. Der letzte Beitrag () ist von Haudruferzappeltnoch.

    FileInfo.Refresh und Exists sind irgendwie lahm

    Hallo,

    ich habe hier ein komisches Phänomen/Problem.
    Folgendes soll passieren
    Ich schreibe eine Datei. Diese Datei liegt auf unbestimmte Zeit (1-6 Sekunden) an ihren Platz und wird dann extern gelöscht (das muss auch so passieren). Dann schreibe ich eine neue Datei. Das passiert solange bis eine Liste abgearbeitet ist.

    Um das umzusetzen, muss ich also prüfen, dass die Datei definitiv verschwunden ist bevor die nächste drankommt. Nun könnte ich experimentell die maximale Löschzeit ermitteln und immer diese Zeit warten. Das maximiert aber leider die Gesamtabarbeitungszeit der Liste, da dann immer diese Zeit gewartet wird, obwohl auch kürzere Zeitfenster zwischendurch drin wären.

    Das beste wäre wohl ein FileSystemWatcher. Aber da ich das Ding ja gern meide wie der Teufel das Weihwasser, hab ichs erstmal versucht mit alle 2 Sekunden nachgucken per FileInfo.Refresh und FileInfo.Exists.
    Das ganze läuft asynchron wegen ner ganz anderen Thematik.
    Die Schleife in etwa:

    VB.NET-Quellcode

    1. Task.Run(Sub()
    2. For Each request In Requests
    3. SendTo(dest, request)
    4. Next
    5. End Sub)
    6. Private Sub SendTo(dest As FileInfo, req As Request)
    7. Dim tryCount = 0
    8. While tryCount < 3
    9. Task.Delay(2000).Wait()
    10. dest.Refresh
    11. If Not dest.Exists Then
    12. File.WriteAllText(dest.Fullname, req.ToString)
    13. Exit While
    14. End If
    15. tryCount += 1
    16. End While
    17. End Sub
    Und irgendwie scheint das Refresh hier nicht richtig hinzuhauen. Der erkennt das nicht immer, dass die Datei weg ist wenn sie weg ist. Man merkt, dass der zu langsam ist. (Zu oft durchs While läuft)

    Mit File.Copy() Exception klappt das besser

    VB.NET-Quellcode

    1. Task.Run(Sub()
    2. For Each request In Requests
    3. SendTo(dest, request)
    4. Next
    5. End Sub)
    6. Private Sub SendTo(dest As FileInfo, req As Request)
    7. File.WriteAllText(myPath, req.ToString)
    8. Dim tryCount = 0
    9. While tryCount < 3
    10. Task.Delay(2000).Wait()
    11. Try
    12. File.Copy(myPath, dest.FullName, False)
    13. Exit While
    14. Catch ex As IOException
    15. tryCount += 1
    16. End Try
    17. End While
    18. End Sub
    Eine Idee dazu? Der prüft den Pfad (dest) über ein Netzwerk hinweg, vielleicht irgendeine Besonderheit dadran?

    Ich werds aber nun doch mit dem FileSystemWatcher probieren, ich schätze der händelt das genau so wie es muss, wenn man denn erstmal die Unzuverlässigkeit bei dem Ding gepatcht hat.

    Viele Grüße

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Haudruferzappeltnoch“ ()

    Hallo,
    was ist an dem FileSystemWatcher verkehrt und warum meidest du den? Es ist doch einfacher den einmalig im Programmablauf zu konfigurieren, als in einer Schleife darauf zu warten, dass eine Datei gelöscht wurde.

    C#-Quellcode

    1. ​using FileSystemWatcher watcher = new(@"\\network\share", "*.txt");
    2. watcher.NotifyFilter = NotifyFilters.LastWrite;
    3. watcher.Deleted += (sender, e) => {
    4. Console.WriteLine(e.Name);
    5. };
    6. watcher.IncludeSubdirectories = false;
    7. watcher.EnableRaisingEvents = true;
    8. Console.WriteLine("Demo");
    9. Console.ReadLine();
    Weil der nicht merkt, wenn die Verbindung mal ausfällt. Danach funktionslos ohne Meldung, muss man halt extra was für patchen. Wenn der in ner Anwendung sitzt die länger läuft, muss man den regelmäßig, was weiß ich stündlich/täglich mal frisch machen oder prüfen, ob alles noch paletti is.

    Aber um die Methodik gehts mir nicht. Eher um das Phänomen/Funktionsweise von Refresh
    Hat sich gut angehört, erstaunlicherweise geht das auch nicht besser. Der failed sich da munter durch. Manchmal sogar zwei volle SendTos hintereinander. Aber immer volle SendTos entweder es klappt beim ersten Versuch oder gar nicht, ganz merkwürdig. Ohman ich hatte das Exit While da noch nicht drin, deswegen manchmal meherere SendTos und volle SendTos.
    Aber nichtsdestotrotz, auch mit Exit While besteht verzögerte Erkenntnis, dass die Datei weg ist. Das heißt dann ja wohl irgendwo liegt noch die Information, dass das File da ist, obwohl es weg ist.

    VB.NET-Quellcode

    1. Task.Run(Sub()
    2. For Each request In Requests
    3. SendTo(dest, request)
    4. Next
    5. End Sub)
    6. Private Sub SendTo(dest As String, req As Request)
    7. Dim tryCount = 0
    8. While tryCount < 3
    9. Task.Delay(2000).Wait()
    10. Dim fi = New FileInfo(dest)
    11. If Not fi.Exists Then
    12. File.WriteAllText(fi.FullName, req.ToString)
    13. Exit While
    14. End If
    15. CWrite("Fail" & tryCount) 'damit ich die Fails sehe
    16. tryCount += 1
    17. End While
    18. End Sub

    Habe außerdem die FSW-Version umgesetzt. Soviel zu einfacher... Aber läuft wie geschmiert. Da gibt es null Aussetzer oder Verzögerungen, was die Datei Beobachtung angeht
    Da ich nicht mehr explizit selbst Wartezeiten einbauen muss, ist dieser Ansatz außerdem synchron machbar. (Vielleicht hat es auch mit der synchronizität zu tun?)
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class FooWorker
    2. Private Const FileName = "foo.txt"
    3. Private ReadOnly workPath As String
    4. Private ReadOnly FullFileName As String
    5. Private Requests As List(Of Request)
    6. Private ReqIndex As Integer
    7. Private WithEvents FSW As FileSystemWatcher
    8. Private WithEvents timeDispose As Timers.Timer
    9. Private _Running As Boolean
    10. Friend Event FSWDeactivated As EventHandler
    11. Friend ReadOnly Property Running As Boolean
    12. Get
    13. Return _Running
    14. End Get
    15. End Property
    16. Sub New(dir As String, SynchronizingObject As Object)
    17. workPath = dir
    18. FullFileName = Path.Combine(workPath, FileName)
    19. timeDispose = New Timers.Timer(1000) With {.AutoReset = False,
    20. .Enabled = False, .SynchronizingObject = SynchronizingObject}
    21. End Sub
    22. Friend Sub StartUp(reqs As List(Of Request))
    23. If reqs.Count = 0 Then Throw New Exception("Request list cannot be empty.")
    24. _Running = True
    25. Requests = reqs
    26. ReqIndex = reqs.Count - 1
    27. FSW = New FileSystemWatcher With {.Filter = FileName,
    28. .Path = workPath, .SynchronizingObject = timeDispose.SynchronizingObject,
    29. .EnableRaisingEvents = True, .NotifyFilter = NotifyFilters.FileName}
    30. File.WriteAllText(FullFileName, Requests(ReqIndex).ToString)
    31. End Sub
    32. Friend Sub ShutDown()
    33. timeDispose.Stop()
    34. FSW.Dispose()
    35. FSW = Nothing
    36. _Running = False
    37. RaiseEvent FSWDeactivated(Me, Nothing)
    38. End Sub
    39. Friend Function CancelFSW() As Boolean
    40. ShutDown()
    41. Return True
    42. End Function
    43. Private Sub FSW_Deleted(sender As Object, e As FileSystemEventArgs) Handles FSW.Deleted
    44. If ReqIndex > 0 Then
    45. ReqIndex -= 1
    46. Else
    47. timeDispose.Start()
    48. Exit Sub
    49. End If
    50. File.WriteAllText(FullFileName, Requests(ReqIndex).ToString)
    51. End Sub
    52. Private Sub timeDispose_Elapsed(sender As Object, e As ElapsedEventArgs) Handles timeDispose.Elapsed
    53. ShutDown()
    54. End Sub
    55. End Class

    Dieser Beitrag wurde bereits 11 mal editiert, zuletzt von „Haudruferzappeltnoch“ ()