2009-09-11 12 views
16

En C# /. NET (en Windows), ¿hay alguna forma de leer un archivo "creciente" utilizando una secuencia de archivos? La longitud del archivo será muy pequeña cuando se abra la secuencia de archivos, pero otro subproceso lo va a escribir. Si/cuando la extensión de archivos "alcanza" al otro subproceso (es decir, cuando Read() devuelve 0 bytes de lectura), quiero hacer una pausa para permitir que el archivo se búfere un poco, luego continúe leyendo.¿Lees de un archivo creciente en C#?

Realmente no quiero usar un FilesystemWatcher y seguir creando nuevas secuencias de archivos (como se sugirió para los archivos de registro), ya que no es un archivo de registro (es un archivo de video codificado sobre la marcha) y el rendimiento es un problema

Gracias,
Robert

+0

He actualizado mi respuesta. –

Respuesta

6

Puede hacer esto, pero necesita mantener un seguimiento cuidadoso de las posiciones de lectura y escritura de archivos usando Stream.Seek y con la sincronización adecuada entre los hilos. Por lo general, debería usar un EventWaitHandle o una subclase del mismo para realizar la sincronización de los datos, y también debería tener en cuenta la sincronización para el acceso al objeto FileStream (probablemente a través de una declaración lock).

Actualización: Al responder this question he implementado algo similar - una situación en la que un archivo se está descargando en segundo plano y siendo también subido al mismo tiempo. Usé memorias intermedias de memoria y publiqué un gist que tiene código de trabajo. (Es GPL pero puede no importarle, en cualquier caso puede usar los principios para hacer lo suyo.)

+0

Voy a ver esto ... para las patadas, ¿podría ser más fácil simplemente escribir el resultado de la codificación en la memoria (es decir, utilizando un doble buffer) y luego enviarlo al archivo de red y caché al mismo tiempo? –

4

La forma en que resolvió esto es usar la clase DirectoryWatcher/FileSystemWatcher, y cuando se dispara en el archivo que desea abrir un FileStream y leer hasta el final. Y cuando termine de leer, guardo la posición del lector, así que la próxima vez que el DirectoryWatcher/FilesystemWatcher se active, abriré una secuencia y fijaré la posición donde estaba la última vez.

Llamar a FileStream.length es realmente muy lento, no he tenido problemas de rendimiento con mi solución (estaba leyendo un "registro" que oscilaba entre 10mb y 50 ish).

Para mí, la solución que describo es muy simple y fácil de mantener, la probaría y la perfilaría. No creo que tengas problemas de rendimiento basados ​​en eso. Hago esto cuando personas están jugando un juego de múltiples hilos, tomando toda su CPU y nadie se ha quejado de que mi analizador es más exigente que los analizadores de la competencia.

+1

La pregunta específicamente descuenta el uso de un observador, debido a problemas de rendimiento. –

+0

Sí, me di cuenta. agregué más a mi respuesta con respecto a la preformance. – EKS

+0

No es necesario que invoque FileStream.Length en el lector si todo lo que hace es leer todo lo que pueda y luego esperar a que aparezcan más datos. ¿Qué tipo de latencia estás viendo para el gatillo del observador? ¿Eso cambia dependiendo de la carga de la máquina? –

2

Otra cosa que podría ser útil es que la clase FileStream tiene una propiedad llamada ReadTimeOut que es se define como:

Obtiene o establece un valor, en milisegundos, que determina cuánto tiempo la secuencia intentará leer antes de que se agote el tiempo de espera. (Se hereda de Stream)

Esto podría ser útil porque cuando las lecturas se ponen al día, el hilo que realiza las lecturas puede pausarse mientras se vacía el búfer de escritura. Definitivamente valdría la pena escribir una pequeña prueba para ver si esta propiedad ayudaría a su causa de alguna manera.

¿Las operaciones de lectura y escritura ocurren en el mismo objeto? Si es así, podría escribir sus propias abstracciones sobre el archivo y luego escribir el código de comunicación cruzado tal que el hilo que está realizando las escrituras y notificar al hilo que realiza las lecturas cuando esté hecho para que el hilo que lee sepa cuándo dejar de leer cuando alcanza EOF

+0

¿Cómo podría esta respuesta obtener +3 si la configuración de ReadTimeOut en FileStream genera una excepción? : S –

4

Esto funcionó con un StreamReader en torno a un archivo, con los siguientes pasos:

  1. en el programa que escribe en el archivo, abrirlo con el uso compartido de lectura, así:

    var out = new StreamWriter(File.Open("logFile.txt", FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read)); 
    
  2. En el programa que lee el archivo, abrirlo con el intercambio de lectura y escritura, así:

    using (FileStream fileStream = File.Open("logFile.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) 
    using (var file = new StreamReader(fileStream)) 
    
  3. Antes de acceder al flujo de entrada, verifique si se ha alcanzado el final, y si es así, espere un momento.

    while (file.EndOfStream) 
    { 
        Thread.Sleep(5); 
    } 
    
Cuestiones relacionadas