Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is It Possible To Raise An Event When A File Becomes Accessible?

Tags:

c#

.net

file-io

In C# I can use the FileSystemWatcher object to watch for a specific file and raise an event when it is created, modified, etc.

The problem I have with this class is that it raises the event the moment the file becomes created, even if the process which created the file is still in the process of writing. I have found this to be very problematic, especially if I'm trying to read something like an XML document where the file must have some structure to it which won't exist until it is completed being written.

Does .NET (preferably 2.0) have any way to raise an event after the file becomes accessible, or do I have to constantly try reading the file until it doesn't throw an exception to know it is available?

like image 825
Dan Herbert Avatar asked Aug 23 '08 15:08

Dan Herbert


1 Answers

You can use a file system watcher to check when the file has been changed. It only becomes "changed" after whichever program had the file previously closes the file. I know you asked for C#, but my VB.Net is much better. Hope you or someone else can translate.

It tries to open the file, if it isn't available, it adds a watcher, and waits for the file to be changed. After the file is changed, it tries to open again. It throws an exception if it waits more than 120 seconds, because you may get caught in a situation where the file is never released. Also, I decided to add a timeout of waiting for the file change of 5 seconds, in case of the small possibility that the file was closed prior to the actual file watcher being created.

 Public Sub WriteToFile(ByVal FilePath As String, ByVal FileName As String, ByVal Data() As Byte)
        Dim FileOpen As Boolean
        Dim File As System.IO.FileStream = Nothing
        Dim StartTime As DateTime
        Dim MaxWaitSeconds As Integer = 120

        StartTime = DateTime.Now

        FileOpen = False

        Do
            Try
                File = New System.IO.FileStream(FilePath & FileName, IO.FileMode.Append)
                FileOpen = True

            Catch ex As Exception

                If DateTime.Now.Subtract(StartTime).TotalSeconds > MaxWaitSeconds Then
                    Throw New Exception("Waited more than " & MaxWaitSeconds & " To Open File.")
                Else
                    Dim FileWatch As System.IO.FileSystemWatcher

                    FileWatch = New System.IO.FileSystemWatcher(FilePath, FileName)
                    FileWatch.WaitForChanged(IO.WatcherChangeTypes.Changed,5000)
                End If

                FileOpen = False

            End Try

        Loop While Not FileOpen

        If FileOpen Then
            File.Write(Data, 0, Data.Length)
            File.Close()
        End If
    End Sub
like image 114
Kibbee Avatar answered Oct 01 '22 23:10

Kibbee