当文件变得可访问时是否可以引发事件?

时间:2008-08-23 15:54:57

标签: c# .net file-io

在C#中,我可以使用FileSystemWatcher对象来监视特定文件,并在创建,修改等事件时引发事件。

我在这个类中遇到的问题是它会在文件创建的那一刻引发事件,即使创建文件的进程仍在编写过程中。我发现这是非常有问题的,特别是如果我正在尝试读取类似XML文档的内容,其中文件必须具有某种结构,在完成编写之前它将不存在。

.NET(最好是2.0)是否有任何方法可以在文件可访问后引发事件,或者我是否必须不断尝试读取该文件,直到它没有抛出异常才知道它可用?

4 个答案:

答案 0 :(得分:5)

您可以使用文件系统观察程序检查文件何时更改。只有在文件先前关闭文件的程序之后,它才会变为“已更改”。我知道你要求C#,但我的VB.Net要好得多。希望你或其他人可以翻译。

它尝试打开文件,如果它不可用,它会添加一个观察程序,并等待文件被更改。文件更改后,它会再次尝试打开。如果等待超过120秒,它会抛出异常,因为您可能会遇到永远不会释放文件的情况。此外,我决定添加等待文件更改5秒的超时,以防在创建实际文件观察程序之前文件被关闭的可能性很小。

 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

答案 1 :(得分:0)

不确定标准类是否实际上有一种事件被引发,但我在最近的一些工作中遇到了类似的问题。

简而言之,我试图写入当时锁定的文件。我最终将write方法包装起来,以便在...之后的几毫秒内自动再次尝试写入。

大声思考,你可以探测文件的ReadOnly状态吗?可能值得拥有文件IO的包装器,它可以为未决文件操作或其他东西堆叠代表。想法?

答案 2 :(得分:0)

在带有OPEN_ EXISTING标志和FILE_ ALL_ ACCESS的循环中使用CreateFile(或者您可能只需要一个子集,请参阅http://msdn.microsoft.com/en-us/library/aa364399(VS.85).aspx

检查返回的句柄-1(INVALID_ HANDLE_ VALUE)是否失败。它仍然是轮询,但这将节省异常抛出的成本。

编辑:此编辑器/标记无法处理下划线!呸!

答案 3 :(得分:0)

Kibbe的答案似乎没错,但对我没用。似乎FileSystemWatcher有一个bug。所以我写了自己的WaitForChanged:

using (var watcher = new FileSystemWatcher(MatlabPath, fileName))
{
    var wait = new EventWaitHandle(false, EventResetMode.AutoReset);
    watcher.EnableRaisingEvents = true;
    watcher.Changed += delegate(object sender, FileSystemEventArgs e)
    {
       wait.Set();
    };
    if (!wait.WaitOne(MillissecondsTimeout))
    {
        throw new TimeoutException();
    }
 }