c# - used - IOException: el proceso no puede acceder al archivo ''ruta del archivo'' porque está siendo utilizado por otro proceso
system io ioexception file used by another process c# (5)
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 programa, 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 declaración 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 reintento . 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 , networking 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 :
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 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
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 programa 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 reintento , 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 this y this 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 .
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 Waiting "para que la tarea complete la ejecución":
using (var wc = new WebClient())
{
var tskResult = wc.UploadFileTaskAsync(_address, _fileName);
tskResult.Wait();
}
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