IOException: el proceso no puede acceder al archivo ‘ruta del archivo’ porque está siendo utilizado por otro proceso

Tengo un código y cuando se ejecuta, arroja una IOException , diciendo que

El proceso no puede acceder al archivo ‘nombre de archivo’ porque está siendo utilizado por otro proceso

¿Qué significa esto y qué puedo hacer al respecto?

¿Cual es la causa?

El mensaje de error es bastante claro: está intentando acceder a un archivo, y no es accesible porque otro proceso (o incluso el mismo proceso) está haciendo algo con él (y no permitió compartirlo).

Depuración

Puede ser bastante fácil de resolver (o bastante difícil de entender), dependiendo de su escenario específico. Veamos algunos.

Tu proceso es el único para acceder a ese archivo
Estás seguro de que el otro proceso es tu propio proceso. Si sabe que abre ese archivo en otra parte de su progtwig, antes que nada debe verificar que cierre correctamente el identificador del archivo después de cada uso. Aquí hay un ejemplo de código con este error:

 var stream = new FileStream(path, FileAccess.Read); var reader = new StreamReader(stream); // Read data from this file, when I'm done I don't need it any more File.Delete(path); // IOException: file is in use 

Afortunadamente, FileStream implementa IDisposable , por lo que es fácil ajustar todo el código dentro de una statement using :

 using (var stream = File.Open("myfile.txt", FileMode.Open)) { // Use stream } // Here stream is not accessible and it has been closed (also if // an exception is thrown and stack unrolled 

Este patrón también asegurará que el archivo no se deje abierto en caso de excepciones (puede ser la razón por la que el archivo está en uso: algo salió mal y nadie lo cerró; vea esta publicación para ver un ejemplo).

Si todo parece estar bien (está seguro de que siempre cierra todos los archivos que abre, incluso en caso de excepciones) y tiene múltiples hilos de trabajo, entonces tiene dos opciones: volver a trabajar el código para serializar el acceso al archivo (no siempre factible y no siempre quería) o aplicar un patrón de rebash . Es un patrón bastante común para operaciones de E / S: intenta hacer algo y en caso de error espera e intenta de nuevo (¿se preguntó por qué, por ejemplo, Windows Shell tarda un tiempo en informarle que un archivo está en uso? y no puede ser eliminado?). En C # es bastante fácil de implementar (ver también mejores ejemplos sobre E / S de disco , redes y acceso a la base de datos ).

 private const int NumberOfRetries = 3; private const int DelayOnRetry = 1000; for (int i=1; i <= NumberOfRetries; ++i) { try { // Do stuff with file break; // When done we can break loop } catch (IOException e) when (i <= NumberOfRetries) { // You may check error code to filter some exceptions, not every error // can be recovered. Thread.Sleep(DelayOnRetry); } } 

Tenga en cuenta un error común que vemos muy a menudo en StackOverflow:

 var stream = File.Open(path, FileOpen.Read); var content = File.ReadAllText(path); 

En este caso, ReadAllText() fallará porque el archivo está en uso ( File.Open() en la línea anterior). Abrir el archivo de antemano no solo es innecesario, sino también incorrecto. Lo mismo se aplica a todas las funciones de File que no devuelven un identificador al archivo con el que está trabajando: File.ReadAllText() , File.WriteAllText() , File.ReadAllLines() , File.WriteAllLines() y otros (como File.AppendAllXyz() funciones File.AppendAllXyz() abrirán y cerrarán el archivo por sí mismas.

Tu proceso no es el único para acceder a ese archivo
Si su proceso no es el único para acceder a ese archivo, entonces la interacción puede ser más difícil. Un patrón de rebash ayudará (si el archivo no debe ser abierto por otra persona pero lo es, entonces necesita una utilidad como Process Explorer para verificar quién está haciendo qué ).

Formas de evitar

Cuando corresponda, siempre use las instrucciones de uso para abrir archivos. Como se dijo en el párrafo anterior, lo ayudará activamente a evitar muchos errores comunes (consulte este artículo para ver un ejemplo sobre cómo no usarlo ).

Si es posible, intente decidir a quién pertenece el acceso a un archivo específico y centralice el acceso a través de algunos métodos bien conocidos. Si, por ejemplo, tiene un archivo de datos donde su progtwig lee y escribe, entonces debe incluir todo el código de E / S dentro de una sola clase. Facilitará la depuración (porque siempre puede poner un punto de interrupción allí y ver quién está haciendo qué) y también será un punto de sincronización (si es necesario) para el acceso múltiple.

No olvide que las operaciones de E / S siempre pueden fallar, un ejemplo común es este:

 if (File.Exists(path)) File.Delete(path); 

Si alguien borra el archivo después de File.Exists() pero antes de File.Delete() , lanzará una IOException en un lugar donde puede sentirse equivocado.

Cuando sea posible, aplique un patrón de rebash , y si está utilizando FileSystemWatcher , considere posponer la acción (porque se lo notificará, pero una aplicación aún puede estar trabajando exclusivamente con ese archivo).

Escenarios avanzados
No siempre es tan fácil, por lo que es posible que deba compartir el acceso con otra persona. Si, por ejemplo, está leyendo desde el principio y escribiendo hasta el final, tiene al menos dos opciones.

1) comparte el mismo FileStream con las funciones de sincronización adecuadas (porque no es seguro para subprocesos ). Vea esto y estas publicaciones para ver un ejemplo.

2) use la enumeración de FileShare para indicar al sistema operativo que permita que otros procesos (u otras partes de su propio proceso) accedan al mismo archivo al mismo tiempo.

 using (var stream = File.Open(path, FileMode.Open, FileAccess.Write, FileShare.Read)) { } 

En este ejemplo, mostré cómo abrir un archivo para escribir y compartir para leer; tenga en cuenta que cuando se superponen la lectura y la escritura, da como resultado datos no definidos o no válidos. Es una situación que se debe manejar al leer. También tenga en cuenta que esto no hace que el acceso a la stream seguro para la ejecución de subprocesos, por lo que este objeto no se puede compartir con múltiples subprocesos a menos que el acceso se sincronice de alguna manera (consulte los enlaces anteriores). Otras opciones para compartir están disponibles y abren escenarios más complejos. Consulte MSDN para obtener más detalles.

En general, N procesos pueden leer desde el mismo archivo, pero solo uno debería escribir, en un escenario controlado incluso puede habilitar escritos concurrentes, pero esto no se puede generalizar en pocos párrafos de texto dentro de esta respuesta.

¿Es posible desbloquear un archivo utilizado por otro proceso? No siempre es seguro y no es tan fácil, pero sí, es posible .

Tuve un problema al cargar una imagen y no pude eliminarla y encontré una solución. gl hf

 //C# .NET var image = Image.FromFile(filePath); image.Dispose(); // this removes all resources //later... File.Delete(filePath); //now works 

El uso de FileShare solucionó mi problema de abrir el archivo incluso si lo abre otro proceso.

 using (var stream = File.Open(path, FileMode.Open, FileAccess.Write, FileShare.ReadWrite)) { } 

Obtuve este error porque estaba haciendo File.Move en una ruta de archivo sin un nombre de archivo, necesito especificar la ruta completa en el destino.

Tuve la siguiente situación que causaba el mismo error:

  • Subir archivos al servidor
  • Luego deshazte de los archivos viejos después de que se hayan cargado

La mayoría de los archivos eran de pequeño tamaño, sin embargo, algunos eran grandes y, por lo tanto, al intentar eliminarlos se produjo un error al acceder al archivo .

No fue fácil de encontrar, sin embargo, la solución fue tan simple como esperar “para que la tarea complete la ejecución”:

 using (var wc = new WebClient()) { var tskResult = wc.UploadFileTaskAsync(_address, _fileName); tskResult.Wait(); } 

Como han señalado otras respuestas en este hilo, para resolver este error debe inspeccionar cuidadosamente el código, para comprender dónde se bloquea el archivo.

En mi caso, estaba enviando el archivo como un archivo adjunto de correo electrónico antes de realizar la operación de movimiento.

Así que el archivo se bloqueó durante unos segundos hasta que el cliente SMTP terminó de enviar el correo electrónico.

La solución que adopté fue mover primero el archivo y luego enviar el correo electrónico. Esto resolvió mi problema.

Otra posible solución, como señaló Hudson anteriormente, habría sido eliminar el objeto después de su uso.

 public static SendEmail() { MailMessage mMailMessage = new MailMessage(); //setup other email stuff if (File.Exists(attachmentPath)) { Attachment attachment = new Attachment(attachmentPath); mMailMessage.Attachments.Add(attachment); attachment.Dispose(); //disposing the Attachment object } } 

Vaya a la ruta del archivo y elimínelo, y luego inicie Android Studio nuevamente, puede haber conflicto entre dos archivos.