2010-09-17 69 views
9

Tengo un programa que hace esto más o menos:archivo está siendo utilizado por otro proceso

  1. abrir un archivo para leer de él.
  2. cerrar el archivo
  3. Iniciar un administrador de archivos para ver los cambios en el archivo.
  4. Tan pronto como se detecta un cambio, bandera EnableRaisingEvents del FileWatcher se establece en false y el proceso se repite desde el paso 1.

El problema es, después de ir desde el paso 4 al paso 1, no puede leer el archivo que dice que está siendo utilizado por otro Proceso.

error recibo:

Excepción no controlada: System.IO.IOException: El proceso no tiene acceso al archivo 'c: \ test.xml' porque está siendo utilizado por otro proceso.

¿Qué está mal? ¿El lector del Paso 1 de mi programa todavía tiene el archivo abierto, o hay algún proceso completamente diferente accediendo al archivo, o es que el guardián de archivos sigue mirando el archivo después de pasar al Paso 1 de 4, a pesar de establecer el indicador en falso?

+0

Se puede publicar su código. Eso puede ayudarnos a responder su pregunta. – klabranche

+1

Publica un código. Ayúdanos a ayudarte –

+1

El código es un tanto enorme y confidencial ya que es para una empresa financiera, pero veré si puedo hacerlo seguro y publicarlo. – xbonez

Respuesta

8

Si el código es similar a esto:

[STAThread] 
static void Main(string[] args) 
{ 
    string file = "temp.txt"; 
    ReadFile(file); 
    FileSystemWatcher fswatcher = new FileSystemWatcher(".\\"); 
    fswatcher.Changed += delegate(object sender, FileSystemEventArgs e) 
          { 
           ReadFile(e.FullPath); 
          }; 
    while (true) 
    { 
     fswatcher.WaitForChanged(WatcherChangeTypes.Changed); 
    } 
} 
private static void ReadFile(string file) 
{ 
    Stream stream = File.OpenRead(file); 
    StreamReader streamReader = new StreamReader(stream); 
    string str = streamReader.ReadToEnd(); 
    MessageBox.Show(str); 
    streamReader.Close(); 
    stream.Close(); 
} 

Si está editando el archivo mediante el Bloc de notas y, a continuación, cuando se haga clic en el botón Guardar, mantiene el archivo abierto, mientras que si cierra el programa y hace clic en guardarlo no. No sé si esto es un error o una característica no documentada del bloc de notas, pero este podría ser su problema.Una forma de solucionar esto es hacer lo siguiente:

En su delegado anónimo, o donde sea que ejecute la llamada al ReadFile(), llame al , para que el programa espere antes de leer el archivo y su código funcione correctamente.

+1

Thread.Sleep parece haber resuelto el problema. ¡Gracias! – xbonez

+0

@xbonez: este código funciona bien para mí, incluso sin 'Thread.Sleep()'. (Cambié 'MessageBox.Show' a' Console.WriteLine') Sin embargo, aún usaría una declaración 'using'. – JohnB

+0

Después de jugar un poco más, descubrí que si tengo dos instancias de este programa viendo el mismo archivo, cuando hago clic en "Guardar" en el Bloc de notas, obtengo este error de una de las instancias (el otro continúa ejecutándose): 'El proceso no puede acceder al archivo 'c: \ file.txt' porque está siendo utilizado por otro proceso. – JohnB

4

Usted puede utilizar una herramienta como Process Explorer de http://www.sysinternals.com para ver quién tiene el identificador abierto en el proceso

El archivo es más probable que mantiene abierta por lo que causó la notificación de cambio a fuego en el primer lugar.

+0

+1 para el explorador de procesos. – NotMe

0

Hay una serie de cosas que podrían estar sucediendo.

Primero, asegúrese de desechar correctamente la grabadora de archivos (cerrar no es lo suficientemente bueno) utilizando la cláusula using alrededor de todo lo que implemente IDisposable.

En segundo lugar, si simplemente está leyendo, asegúrese de tener los indicadores correctos establecidos al abrir el archivo.

Para ir más lejos, sería útil que proporcionaras un bloque de código que mostrara cómo lo estás logrando; particularmente alrededor de la lectura del archivo

+0

+1: acepto, uso declaraciones 'using' – JohnB

3

Nota: incluso si "file.txt" está abierto en el Bloc de notas, este código aún funciona, porque está abierto para lectura.

using System; 
using System.IO; 

class Program 
{ 
    static void Main(string[] args) 
    { 
    ReadFromFile(@"C:\file.txt"); 
    Console.ReadLine(); 
    } 

    static void ReadFromFile(string filename) 
    { 
    string line; 
    using (StreamReader sr = File.OpenText(filename)) 
    { 
     line = sr.ReadLine(); 
     while (line != null) 
     { 
     Console.WriteLine(str); 
     line = sr.ReadLine(); 
     } 
     sr.Close(); 
    } 
    } 
} 

O simplemente:

string text = System.IO.File.ReadAllText(@"C:\file.txt");

3

Además de otras respuestas es posible que cuando FileWatcher reaccione el archivo aún no esté cerrado por esa aplicación. En el paso 1 intenta no fallar inmediatamente, pero intenta varios intentos con un pequeño retraso.

0

Puede usar esta utilidad de MS openfiles para obtener la lista de archivos abiertos y comprender quién ha abierto el archivo.

openfiles /query 

También permite desconectar los archivos abiertos por los usuarios de la red.

openfiles /disconnect /id XXXX 

Si desea utilizarlo para PC local debe establecer Mantener lista de objetos indicador global:

openfiles /local on 

Siga el link para obtener más detalles.

Cuestiones relacionadas