Сведения о вопросе

Fhohir

23:32, 8th August, 2020

Теги

c#   .net   file-io    

Можно Ли Вызвать Событие, Когда Файл Становится Доступным?

Просмотров: 494   Ответов: 4

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

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

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



  Сведения об ответе

LAST

22:55, 7th August, 2020

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


  Сведения об ответе

LIZA

23:10, 20th August, 2020

Ответ киббе кажется правильным, но не сработал для меня. Похоже, что 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();
    }
 }


  Сведения об ответе

VERSUION

01:34, 17th August, 2020

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

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

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


  Сведения об ответе

padenie

00:19, 11th August, 2020

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

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

EDIT: этот редактор/markup не может обрабатывать подчеркивания! ба!


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться