Можно ли вызвать событие, когда файл становится доступным?

В C # я могу использовать объект FileSystemWatcher, чтобы следить за конкретным файлом и вызывать событие при его создании, изменении и т. Д.

Проблема, с которой я столкнулся в этом классе, заключается в том, что он вызывает событие в тот момент, когда файл создается, даже если процесс, который создал файл, все еще находится в процессе записи. Я обнаружил, что это очень проблематично, особенно если я пытаюсь прочитать что-то вроде XML-документа, в котором файл должен иметь некоторую структуру, которая не будет существовать до тех пор, пока не будет завершена запись.

Есть ли у .NET (предпочтительно 2.0) какой-либо способ вызвать событие после того, как файл станет доступным, или я должен постоянно пытаться читать файл, пока он не выдаст исключение, чтобы узнать, что он доступен?

23.08.2008 15:54:56
4 ОТВЕТА

Не уверен, есть ли способ, чтобы событие было действительно возбуждено стандартным классом, но я столкнулся с похожими проблемами в недавней работе, которую я выполнял.

Короче говоря, я пытался записать файл, который был заблокирован в то время. Я закончил завершение метода записи, так что он автоматически попытался бы снова записать через несколько мс после ..

Размышляя вслух, можете ли вы проверить файл на статус ReadOnly? Может быть, тогда стоит иметь оболочку для файлового ввода-вывода, которая может складывать делегатов для ожидающих файловых операций или чего-то еще ... Мысли?

0
23.08.2008 15:59:13

Используйте CreateFile в цикле с флагом OPEN_ EXISTING и FILE_ ALL_ ACCESS (или вам может понадобиться только подмножество, см. Http://msdn.microsoft.com/en-us/library/aa364399(VS.85).aspx

Проверьте дескриптор, возвращенный против -1 (INVALID_ HANDLE_ VALUE) для сбоя. Это все еще опрос, но это спасет стоимость броска исключения.

РЕДАКТИРОВАТЬ: этот редактор / разметка не может обрабатывать подчеркивания! бах!

0
23.08.2008 16:16:49

Вы можете использовать наблюдателя файловой системы, чтобы проверить, когда файл был изменен. Он становится «измененным» только после того, как программа закрыла файл ранее. Я знаю, что вы просили 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
5
23.08.2008 17:51:41

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();
    }
 }
0
12.07.2009 01:33:20
Пожалуйста, сообщите об этой ошибке в Microsoft по адресу connect.microsoft.com/visualstudio .
John Saunders 12.07.2009 01:34:52
Джон Олдридж уже сделал это
Jader Dias 12.07.2009 01:37:47
Ссылка @JaderDias Connect не работает
Ofek Shilon 16.02.2016 14:41:19