Tengo un código y cuando se ejecuta, arroja un IOException
, diciendo que
El proceso no puede acceder al archivo 'nombre de archivo' porque otro proceso lo está utilizando
¿Qué significa esto y qué puedo hacer al respecto?
c#
.net
language-agnostic
ioexception
Adriano Repetti
fuente
fuente
Respuestas:
¿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. A ver algunos.
Su proceso es el único que accede a ese archivo.
Está seguro de que el otro proceso es suyo. Si sabe que abre ese archivo en otra parte de su programa, antes que nada debe verificar que cierre correctamente el identificador de archivo después de cada uso. Aquí hay un ejemplo de código con este error:
Afortunadamente se
FileStream
implementaIDisposable
, por lo que es fácil envolver todo su código dentro de unausing
declaración:Este patrón también asegurará que el archivo no se dejará 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ó; consulte 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: reelaborar su código para serializar el acceso al archivo (no siempre factible y no siempre deseado) o aplicar un patrón de reintento . Es un patrón bastante común para las operaciones de E / S: intenta hacer algo y, en caso de error, espera e intenta nuevamente (¿se preguntó por qué, por ejemplo, Windows Shell tarda un tiempo en informarle que un archivo está en uso? y no se puede eliminar?). En C # es bastante fácil de implementar (vea también mejores ejemplos sobre E / S de disco , redes y acceso a bases de datos ).
Tenga en cuenta un error común que vemos muy a menudo en StackOverflow:
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 lasFile
funciones que no devuelven un mango para el archivo que está trabajando:File.ReadAllText()
,File.WriteAllText()
,File.ReadAllLines()
,File.WriteAllLines()
y otros (comoFile.AppendAllXyz()
funciones) hará todo lo abren y cierran el archivo por sí mismos.Su proceso no es el único que accede a ese archivo
Si su proceso no es el único que accede a ese archivo, la interacción puede ser más difícil. Un patrón de reintento 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
En su caso, utilizar siempre el uso de declaraciones a los archivos abiertos. Como se dijo en el párrafo anterior, lo ayudará activamente a evitar muchos errores comunes (consulte esta publicación para ver un ejemplo sobre cómo no usarlo ).
Si es posible, intente decidir quién posee el acceso a un archivo específico y centralice el acceso a través de algunos métodos conocidos. Si, por ejemplo, tiene un archivo de datos donde su programa lee y escribe, entonces debe colocar 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 acceso múltiple.
No olvide que las operaciones de E / S siempre pueden fallar, un ejemplo común es este:
Si alguien elimina el archivo después,
File.Exists()
pero antesFile.Delete()
, lo arrojaráIOException
a un lugar en el que puede sentirse incorrectamente seguro.Siempre que sea posible, aplique un patrón de reintento , y si está utilizando
FileSystemWatcher
, considere posponer la acción (porque recibirá una notificación, pero una aplicación aún puede estar funcionando 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) compartir lo mismo
FileStream
con las funciones de sincronización adecuadas (porque no es seguro para subprocesos ). Vea esto y esto publicaciones para un ejemplo.2) utilice la
FileShare
enumeración para indicar al sistema operativo que permita que otros procesos (u otras partes de su propio proceso) accedan al mismo archivo simultáneamente.En este ejemplo, mostré cómo abrir un archivo para escribir y compartir para leer; tenga en cuenta que al leer y escribir superposiciones, se obtienen datos no definidos o no válidos. Es una situación que debe manejarse al leer. También tenga en cuenta que esto no hace que el acceso sea
stream
seguro para subprocesos, por lo que este objeto no se puede compartir con varios subprocesos a menos que el acceso esté sincronizado de alguna manera (ver enlaces anteriores). Hay otras opciones para compartir disponibles y abren escenarios más complejos. Consulte MSDN para más detalles.En general, N procesos pueden leer del mismo archivo todos juntos, pero solo uno debe escribir, en un escenario controlado, incluso puede habilitar escrituras concurrentes, pero esto no puede generalizarse 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 .
fuente
File.Create(path)
, debe agregar.Close()
al final de eso antes de escribir en él. Hay escollos como ese, además de lasusing
declaraciones para escribir los archivos y luego eliminarlos. Debe publicar el código en su pregunta sobre cómo está creando y eliminando su archivo. Pero probablemente se alinea con algo mencionado anteriormente.Directory.SetCreationTimeUTC()
pero falla cuando File Explorer está abierto, alegando que otro proceso está accediendo al directorio. ¿Cómo debo manejar esta situación?El uso de FileShare solucionó mi problema de abrir el archivo incluso si lo abre otro proceso.
fuente
Tuve un problema al subir una imagen y no pude eliminarlo y encontré una solución. gl hf
fuente
Recibí este error porque estaba haciendo File.Move a una ruta de archivo sin un nombre de archivo, necesito especificar la ruta completa en el destino.
fuente
El error indica que otro proceso está intentando acceder al archivo. Tal vez usted o alguien más lo tiene abierto mientras intenta escribirle. "Leer" o "Copiar" generalmente no causa esto, pero escribir o llamar a eliminar en él sí lo haría.
Hay algunas cosas básicas para evitar esto, como han mencionado otras respuestas:
En
FileStream
operaciones, colóquelo en unusing
bloque con unFileShare.ReadWrite
modo de acceso.Por ejemplo:
Tenga en cuenta que
FileAccess.ReadWrite
no es posible si lo usaFileMode.Append
.Me encontré con este problema cuando estaba usando una secuencia de entrada para hacer
File.SaveAs
cuando el archivo estaba en uso. En mi caso, descubrí que en realidad no necesitaba volver a guardarlo en el sistema de archivos, así que terminé eliminando eso, pero probablemente podría haber intentado crear un FileStream en unausing
declaraciónFileAccess.ReadWrite
, al igual que el código encima.Guardar sus datos como un archivo diferente y volver a eliminar el antiguo cuando se descubra que ya no está en uso, luego cambiar el nombre del que se guardó correctamente al nombre del original es una opción. La forma en que se prueba el uso del archivo se realiza a través de
en mi código a continuación, y podría hacerse en un servicio de Windows, en un bucle, si tiene un archivo en particular que desea ver y eliminar regularmente cuando desea reemplazarlo. Si no siempre tiene el mismo archivo, se puede actualizar un archivo de texto o una tabla de base de datos para que el servicio siempre verifique los nombres de los archivos, y luego realice esa verificación de los procesos y, posteriormente, realice el proceso de eliminación y eliminación, como describí en la siguiente opción Tenga en cuenta que necesitará un nombre de usuario y contraseña de cuenta que tenga privilegios de administrador en la computadora determinada, por supuesto, para realizar la eliminación y finalización de los procesos.
Cuando no sabe si un archivo estará en uso cuando intenta guardarlo, puede cerrar todos los procesos que podrían estar usándolo, como Word, si es un documento de Word, antes de guardarlo.
Si es local, puede hacer esto:
Si es remoto, puede hacer esto:
donde
txtUserName
está en la forma deDOMAIN\user
.Digamos que no conoce el nombre del proceso que bloquea el archivo. Entonces, puedes hacer esto:
Tenga en cuenta que
file
debe ser la ruta UNC:\\computer\share\yourdoc.docx
para que elProcess
pueda averiguar en qué computadora está yp.MachineName
ser válido.A continuación se muestra la clase que utilizan estas funciones, que requiere agregar una referencia
System.Management
. El código fue escrito originalmente por Eric J .:fuente
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 mover.
Entonces, el archivo se bloqueó durante un par de 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 deshacerse del objeto después de su uso.
fuente
File.Move()
no funcionará y da el mismo error. Si solo agrego un archivo a un correo electrónico, no creo que sea un error cuando está en uso durante laAttachments.Add()
operación porque esto es solo una operación de copia. Si lo hizo por alguna razón, podría copiarlo en un directorio Temp, adjuntar la copia y eliminar el archivo copiado después. Pero no creo, si el OP quiere modificar un archivo y usar eso, que este tipo de solución (de la que no mostró el código, solo la parte adjunta) funcionaría..Dispose()
siempre es una buena idea, pero no es relevante aquí a menos que el archivo se abra en una operación previa.Tuve el siguiente escenario que estaba causando el mismo error:
La mayoría de los archivos eran pequeños, sin embargo, algunos eran grandes y, por lo tanto, al intentar eliminarlos, no se pudo acceder al archivo .
No fue fácil de encontrar, sin embargo, la solución fue tan simple como Esperar "a que la tarea complete la ejecución":
fuente
El siguiente código resuelve este problema, pero le sugiero que, en primer lugar, necesite comprender qué está causando este problema y probar la solución que puede encontrar cambiando el código
Puedo dar otra forma de resolver este problema, pero una mejor solución es verificar su estructura de codificación e intentar analizar qué hace que esto suceda, si no encuentra ninguna solución, puede ir con este código a continuación
fuente
GC.*()
, probablemente tenga otros problemas con su código. 2) El mensaje está localizado y es frágil , utilice HRESULT en su lugar. 3) Es posible que desee dormirTask.Delay()
(y diez segundos es de alguna manera excesivo en muchos casos). 4) No tiene una condición de salida: este código podría colgarse para siempre. 5) Definitivamente no necesitasgoto
aquí. 6) PorException
lo general, atrapar es una mala idea, en este caso también porque ... 6) Si sucede algo más, se está tragando el error.GC.Collect()
ha sido cuando se trata de algunos objetos COM.