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

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

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

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

Ответы [ 4 ]

5 голосов
/ 23 августа 2008

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

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 голосов
/ 23 августа 2008

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

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

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

0 голосов
/ 23 августа 2008

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...