Warten bis StreamWriter auch wirklich ferig ist

  • C#

Es gibt 12 Antworten in diesem Thema. Der letzte Beitrag () ist von us4711.

    Warten bis StreamWriter auch wirklich ferig ist

    Hallo Forum,

    ich schreibe eine oder mehrere Dateien mit dem StreamWriter.
    Via FileWatcher beobachte ich diese Dateien.

    (Hierauf braucht nich eingegangen zu werden, denn das ist einfach so)

    Nun kann es dazu kommen, dass beim Auslesen der Datei im Event des FileWatchers eine Ausnahme geworfen wird.
    "Datei wird schon von einem anderen Prozess ......"

    Frage:
    Wie kann ich sicherstellen, dass der FileWatcher erst zuschlägt wenn die Datei auch wirklich fertig geschrieben wurde.
    Also auch vom System selbst.

    Im Netz wird empfohlen die Datei so oft zu lesen bis es klappt.
    Das gefällt mir aber nicht.

    Gruss

    mikeb69
    @Mokki

    du hast mich scheinbar nicht richtig verstanden.
    Der code sieht in etwa so aus.

    C#-Quellcode

    1. public void IrgendeineFunktion()
    2. {
    3. using (StreamWriter sw = new StreamWriter())
    4. {
    5. sw.Write("Whatever.File");
    6. }
    7. }
    8. public void EventVomFileSystemWatcher()
    9. {
    10. using (StreamReader sr = new StreamReader())
    11. {
    12. sr.Read("Whatever.File");
    13. }
    14. }


    Beim Lesen wird hin und wieder die beschriebene Ausnahme ausgelöst.
    "Datei wird schon von einem anderen Prozess verwendet ......"
    Der FileSystemWatcher läuft in einem anderen Thread als der Rest der Anwendung.

    Für mich sieht es so aus, als dass Windows noch nicht mit dem Schreiben fertig ist und der FileSystemWatcher schon merkt, dass da was anders ist.

    Ich suche jetzt eine schlaue und elegante Lösung des Problems.
    Im FileSystemWatcher-Thread eine bestimmte Zeit warten ist keine Lösung, da vielleicht eine komplett andere Anwendung die Datei blockiert.
    Der Thread soll die Datei auf jedenfall auslesen und verarbeiten können.

    Wer weiß

    Gruss

    mikeb69
    @mikeb69 Wieviel Zeit ist zwischen diesen beiden Aufrufen (wenn das Schreiben zurückkommt bis zum Beginn des Lesens)?
    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

    nicht viel - hab es nicht gemessen - der FileSystemWatcher scheint mir aber sofort auf die Änderung an der / den Datei(en) anzuschlagen.
    Der Breakpoint wird, beim Debuggen, sofort erreicht.

    Ein paar ms vielleicht.

    Aber was mir gerade so auffällt, ich persönlich nimm eigentlich immer Usings, wie im Code oben.
    Kann das was mit fehlenden Usings zu tun haben ?

    Gruss

    mikeb69
    @RodFromGermany

    im Echten Code sind die Usings nicht drin - da wird der StreamReader bzw. StreamWriter ganz normal instanziert.
    Frag mich gerade ob das was damit zu tun haben könnte.

    Gruss

    mikeb69
    @mikeb69 Wie machst Du die denn zu?
    Ein .Flush() und ein .Close() sollten reichen.
    Vielleicht schlägt der FSW bereits nach dem Flush() zu, das kannst Du ja mal während des Debuggings testen.
    Allerdings würde ich da stets ein using verwenden.
    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!
    Hey, könnte man hier nicht mit Try-Catch-Block arbeiten?
    mal ein bisschen pseudo, da ich nicht zum testen komme gerade

    Spoiler anzeigen
    //wenn lesbar, dann ja, ansonsten halt falsch
    function IsReadable(path as string) As Boolean
    boolean = true
    try
    'hier lesen und wenn es geht:
    return true
    catch ioexception
    'kann nicht lesen
    return false
    end function

    if IsReadable(<DeineDatei>) ...



    @RodFromGermany
    wenn ich es richtig verstehe, kann doch auch ein anderes Programm noch darauf zugreifen- je nachdem kann man nix lesen in diesem Fall.
    Option Strict On!

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Drahuverar“ ()

    @Drahuverar @mikeb69 Wenn Du mit mehreren Programmen gleichzeitig auf eine Datei zugreifen willst, musst Du das beim Öffnen der Datei dem Stream mitteilen.
    Wie instanziierst Du Deine Streamer?
    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!
    Du schreibst, dass du selbst der Auslöser der Schreiboperationen bist. Dann weißt du auch genau, wann du fertig bist: Genau dann, wenn du Close() auf dem Stream aufgerufen hast. Der FileSystemWatcher (den meinst du vmtl. anstelle des FileWatchers) schlägt immer dann an, wenn das System gecachte Daten auf die Platte schreibt. Das kann auch passieren, bevor der Stream geschlossen ist, wie du ja schon festgestellt hast.

    Falls du mit dem FSW ausschließlich Dateien überwachst, die dasselbe Programm schreibt, schlage ich stattdessen ein Event vor. Überwachst du dagegen auch prozess-externe Dateien, wird es schwierig. Möglichweise hilft dir "Event Tracing For Windows" (ETW) weiter. Vielleicht gibt es auch eine WMI-Klasse, die ein entsprechendes Event bereitstellt. Der "Process Monitor" verwendet z.B. ETW und zeigt auch Meldungen über geschlossene Dateien an.
    Gruß
    hal2000
    Meines Wissens reagiert der FSW auch schon auf eine CREATE, also u.U. lange bevor der Stream zu Ende geschrieben ist.
    Garry Tinder hat da ein Workaround geschrieben, DelayedFileSystemWatcher, den ich selbst schon seit einiger Zeit mit Erolg einsetze.
    Vielleich hilft Dir ja dieser Code.