2008-08-23 5 views
7

En C# Puedo utilizar el objeto FileSystemWatcher para ver un archivo específico y generar un evento cuando se crea, modifica, etc.¿Es posible levantar un evento cuando un archivo se vuelve accesible?

El problema que tengo con esta clase es que se genera el evento el momento en el archivo se crea, incluso si el proceso que creó el archivo todavía está en proceso de escritura. He encontrado que esto es muy problemático, especialmente si intento leer algo así como un documento XML donde el archivo debe tener alguna estructura que no existirá hasta que no se complete su escritura.

¿Tiene .NET (preferiblemente 2.0) alguna forma de generar un evento después de que el archivo se vuelve accesible, o tengo que intentar constantemente leer el archivo hasta que no arroje una excepción para saber que está disponible?

Respuesta

0

No estoy seguro de si hay una manera de que un evento sea realmente planteado por la clase estándar, pero puedo experimentar problemas similares en algún trabajo reciente que estaba haciendo.

En resumen, estaba intentando escribir en un archivo que estaba bloqueado en ese momento. Terminé envolviendo el método de escritura para que automáticamente intentara escribir de nuevo en unos pocos ms después ...

Pensando en voz alta, ¿Puedes probar el estado de ReadOnly del archivo? Puede valer la pena tener un contenedor para el archivo IO que puede apilar delegados para operaciones de archivo pendientes o algo así ... ¿Pensamientos?

0

Uso CreateFile en un bucle con OPEN_ EXISTENTE bandera y ACCESO file_ ALL_ (o puede que tenga sólo un subconjunto, ver http://msdn.microsoft.com/en-us/library/aa364399(VS.85).aspx

Examine el mango volvió contra -1 (INVALID_ HANDLE_ VALOR) para el fracaso. Es todavía de votación , pero esto va a ahorrar el costo de un tiro excepción

EDIT:. este editor/marcado no puede manejar guiones bah

5

se puede utilizar un FileSystemWatcher para comprobar si el archivo se ha cambiado!!. Solo se "cambia" después de que el programa que tenía el archivo cierra previamente la fi le. Sé que pediste C#, pero mi VB.Net es mucho mejor. Espero que tú u otra persona puedan traducir.

Intenta abrir el archivo, si no está disponible, agrega un vigilante, y espera a que se cambie el archivo. Después de cambiar el archivo, intenta abrir nuevamente. Lanza una excepción si espera más de 120 segundos, porque puede quedar atrapado en una situación donde el archivo nunca se lanza. Además, decidí agregar un tiempo de espera de espera para el cambio de archivo de 5 segundos, en el caso de la pequeña posibilidad de que el archivo se cerrara antes de que se creara el observador de archivos real.

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

Kibbe parece correcto pero no funcionó para mí. Parece que FileSystemWatcher tiene un error. Así que escribí mi propio 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

Informe este error a Microsoft en http://connect.microsoft.com/visualstudio. –

+0

[John Aldrige] (http://www.devnewsgroups.net/group/microsoft.public.dotnet.framework/topic56372.aspx) ya lo hizo [it] (https://connect.microsoft.com/VisualStudio/feedback/ ViewFeedback.aspx? FeedbackID = 240502) –

+0

@JaderDias El enlace de Connect está roto –

Cuestiones relacionadas