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

Posted

技术标签:

【中文标题】当文件变得可访问时是不是可以引发事件?【英文标题】:Is It Possible To Raise An Event When A File Becomes Accessible?当文件变得可访问时是否可以引发事件? 【发布时间】:2010-09-06 15:53:34 【问题描述】:

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

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

.NET(最好是 2.0)是否有办法在文件变得可访问后引发事件,还是我必须不断尝试读取文件直到它不抛出异常才能知道它可用?

【问题讨论】:

【参考方案1】:

您可以使用文件系统观察程序来检查文件何时被更改。只有在之前有该文件的任何程序关闭该文件后,它才会“更改”。我知道您要求使用 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

【讨论】:

【参考方案2】:

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

简而言之,我试图写入一个当时被锁定的文件。我最终将 write 方法包装起来,这样它会在几毫秒后自动尝试再次写入..

大声思考,你能探测文件的只读状态吗?可能值得拥有一个文件 IO 包装器,它可以为挂起的文件操作或其他东西堆叠委托。想法?

【讨论】:

【参考方案3】:

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

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

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

【讨论】:

【参考方案4】:

Kibbe 的回答似乎是正确的,但对我没有用。似乎 FileSystemWatcher 有一个错误。所以我写了自己的 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();
    
 

【讨论】:

请通过connect.microsoft.com/visualstudio将此错误报告给Microsoft。 John Aldrige 已经做过it @JaderDias Connect 链接已损坏

以上是关于当文件变得可访问时是不是可以引发事件?的主要内容,如果未能解决你的问题,请参考以下文章

引发线程事件时无法访问已处置的对象

当watchOS应用程序使用HKWorkoutSession在后台运行时如何使WCSession可访问

当许多连接同时访问远程数据库的单个实例时,连接池是不是会导致任何可访问性问题

groupbox 中有多个radiobutton钮,当任一选择变化时,引发啥事件?

div 按钮可访问性可点击

[转]NopCommerce之旅: 应用启动