文件可访问时是否可能引发事件?

时间:2020-03-05 18:42:25  来源:igfitidea点击:

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

我使用此类的问题是,即使创建文件的过程仍在编写过程中,它也会在创建文件时引发事件。我发现这很成问题,尤其是当我尝试读取XML文档之类的文件时,该文件必须具有某种结构,直到完成写入,该结构才存在。

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

解决方案

回答

不知道标准班级是否真的有办法引发事件,但是我在最近所做的一些工作中遇到了类似的问题。

简而言之,我试图写入当时被锁定的文件。我结束了对write方法的包装,因此它将在几毫秒后自动尝试再次进行写操作。

大声思考,我们可以探测该文件的只读状态吗?那么可能值得拥有一个文件IO的包装器,该包装器可以将委托进行堆栈以进行未决的文件操作或者其他操作。

回答

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

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

编辑:此编辑器/标记不能处理下划线!呸!

回答

我们可以使用文件系统监视程序来检查何时更改了文件。仅在先前具有该文件的任何程序关闭该文件之后,它才会"更改"。我知道我们要求使用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

回答

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();
    }
 }