IOException: le processus ne peut pas accéder au fichier 'file path' parce qu'il est utilisé par un autre processus

j'ai du code et quand il s'exécute, il lance un IOException , disant que

le processus ne peut pas accéder au fichier "filename" parce qu'il est utilisé par un autre procédé

Qu'est-ce que cela signifie, Et Que puis-je y faire?

124
demandé sur Rob 2014-11-04 20:19:58

6 réponses

Quelle est la cause?

le message d'erreur est assez clair: vous essayez d'accéder à un fichier, et il n'est pas accessible parce qu'un autre processus (ou même le même processus) fait quelque chose avec (et il n'a pas permis le partage).

débogage

il peut être assez facile à résoudre (ou assez difficile à comprendre), selon votre scénario spécifique. Nous allons voir quelques.

votre processus est le seul à accéder à ce fichier

Vous êtes sûr que le processus autre est votre propre processus. Si vous savez que vous ouvrez ce fichier dans une autre partie de votre programme, alors tout d'abord, vous devez vérifier que vous avez correctement fermer le descripteur de fichier après chaque utilisation. Voici un exemple de code avec ce bug:

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

heureusement FileStream met en œuvre IDisposable , il est donc facile d'envelopper tout votre code à l'intérieur d'un using déclaration:

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

Ce modèle garantira également que le fichier ne sera pas laissé ouvert en cas d'exceptions (c'est peut-être la raison pour laquelle le fichier est utilisé: quelque chose a mal tourné, et personne ne l'a fermé; voir ce post pour un exemple).

si tout semble bien (vous êtes sûr que vous fermez toujours chaque fichier que vous ouvrez, même en cas d'exceptions) et que vous avez plusieurs threads de travail, alors vous avez deux options: retravaillez votre code pour sérialiser l'accès au fichier (pas toujours faisable et pas toujours voulu) ou appliquez un retry pattern . C'est un modèle assez courant pour les opérations D'E/S: vous essayez de faire quelque chose et en cas d'erreur vous attendez et essayez à nouveau (vous êtes-vous demandé pourquoi, par exemple, Windows Shell prend un certain temps pour vous informer qu'un fichier est utilisé et ne peut pas être supprimé?). Dans C# c'est assez facile à implémenter (voir aussi de meilleurs exemples à propos de disk I /O , mise en réseau et "1519530920 base de données" access ).

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);
    }
}

s'il vous Plaît noter une erreur commune que nous voyons très souvent sur StackOverflow:

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

dans ce cas ReadAllText() échouera parce que le fichier est en usage ( File.Open() dans la ligne avant). Pour ouvrir le fichier à l'avance n'est pas seulement inutile, mais aussi le mal. La même chose s'applique à toutes les fonctions File qui ne renvoient pas un gérer dans le fichier avec lequel vous travaillez: File.ReadAllText() , File.WriteAllText() , File.ReadAllLines() , File.WriteAllLines() et d'autres (comme les fonctions File.AppendAllXyz() ) ouvriront et fermeront le fichier par eux-mêmes.

votre processus n'est pas le seul à accéder à ce fichier

Si le processus n'est pas le seul à accéder à ce fichier, puis l'interaction peut être plus difficile. Un Rety pattern aidera (si le fichier ne doit pas être ouvert par quelqu'un d'autre mais il est, alors vous avez besoin d'un utilitaire comme Process Explorer pour vérifier qui fait quoi ).

moyens d'éviter

le cas échéant, utilisez toujours en utilisant pour ouvrir les fichiers. Comme dit dans le paragraphe précédent, il va activement vous aider à éviter de nombreuses erreurs communes (voir ce post pour un exemple sur comment ne pas l'utiliser ).

si possible, essayez de décider qui possède l'accès à un fichier spécifique et centralisez l'accès par quelques méthodes bien connues. Si, par exemple, vous avez un fichier de données où votre programme lit et écrit, alors vous devez mettre tous les codes d'e/s dans une seule classe. Cela facilitera le débogage (parce que vous pouvez toujours y mettre un point de rupture et voir qui fait quoi) et ce sera aussi un point de synchronisation (si nécessaire) pour les accès multiples.

N'oubliez pas que les opérations d'E / S peuvent toujours échouer, un exemple courant est le suivant:

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

si quelqu'un supprime le fichier après File.Exists() mais avant File.Delete() , alors il lancera un IOException dans un endroit où vous pouvez vous sentir à tort en sécurité.

dans la mesure du possible, appliquer un Rety pattern , et si vous utilisez FileSystemWatcher , envisager de reporter l'action (parce que vous serez avisé, mais une demande peut toujours fonctionner exclusivement avec ce dossier).

scénarios Avancés

Ce n'est pas toujours facile, donc vous pourriez avoir besoin de partager l'accès avec quelqu'un d'autre. Si, par exemple, vous lisez depuis le début et que vous écrivez jusqu'à la fin, vous avez au moins deux options.

1) partagent le même FileStream avec des fonctions de synchronisation appropriées (parce que il n'est pas sans fil ). Voir ce et ce "1519440920 postes pour un exemple.

2) Utilisez FileShare énumération pour demander à OS de permettre à d'autres processus (ou d'autres parties de votre propre processus) d'accéder au même fichier simultanément.

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

dans cet exemple, j'ai montré comment ouvrir un fichier pour l'écriture et partager pour la lecture; s'il vous plaît noter que lors de la lecture et l'écriture se chevauchent, il en résulte des données non définies ou invalides. C'est une situation qui doit être traitée en lisant. Notez également que cela ne rend pas l'accès au thread stream sûr, de sorte que cet objet ne peut pas être partagé avec plusieurs threads à moins que l'accès ne soit synchronisé d'une manière ou d'une Autre (voir liens précédents). D'autres options de partage sont disponibles, et ils ouvrent des scénarios plus complexes. Veuillez vous référer à MSDN pour plus de détails.

en général N les processus peuvent lire à partir d'un même fichier tous ensemble, mais un seul devrait écrire, dans un scénario contrôlé, vous pouvez même activer les Écritures simultanées, mais cela ne peut pas être généralisé dans quelques paragraphes de texte à l'intérieur de cette réponse.

Est-il possible de déverrouiller un fichier utilisé par un autre processus? Il n'est pas toujours sûr et pas si facile, mais oui, il est possible .

213
répondu Adriano Repetti 2017-10-24 07:29:34

en utilisant FileShare a corrigé mon problème de fichier d'ouverture même s'il est ouvert par un autre processus.

using (var stream = File.Open(path, FileMode.Open, FileAccess.Write, FileShare.ReadWrite))
{
}
5
répondu Muhammad Umar 2018-02-08 16:25:21

a eu un problème en téléchargeant une image et ne pouvait pas l'effacer et a trouvé une solution. gl hf

//C# .NET
var image = Image.FromFile(filePath);

image.Dispose(); // this removes all resources

//later...

File.Delete(filePath); //now works
4
répondu Hudson 2018-01-07 19:14:07

j'ai eu cette erreur parce que je faisais du fichier.Déplacer vers un chemin de fichier sans nom de fichier, besoin de spécifier le chemin complet dans la destination.

2
répondu live-love 2018-02-23 15:29:14

j'ai eu le scénario suivant qui causait la même erreur:

  • Télécharger des fichiers sur le serveur
  • puis se débarrasser des vieux fichiers après qu'ils ont été téléchargés

la plupart des fichiers étaient de petite taille, cependant, quelques-uns étaient de grande taille, et donc tenter de les supprimer a abouti à impossible d'accéder au fichier erreur.

il n'a pas été facile de trouver, cependant, le la solution était aussi simple que attente pour la tâche d'exécution complète":

using (var wc = new WebClient())
{
   var tskResult = wc.UploadFileTaskAsync(_address, _fileName);
   tskResult.Wait(); 
}
1
répondu usefulBee 2017-07-24 21:23:58

Comme d'autres réponses dans ce fil de discussion ont souligné, pour résoudre cette erreur, vous devez vérifier attentivement le code, pour comprendre où le fichier est verrouillé.

dans mon cas, j'envoyais le fichier en pièce jointe avant d'effectuer l'opération de déménagement.

donc le fichier a été verrouillé pendant quelques secondes jusqu'à ce que le client SMTP finisse d'envoyer l'e-mail.

la solution que j'ai adoptée était de déplacer le déposer d'abord, puis envoyez-le. Cela a résolu le problème pour moi.

une autre solution possible, comme L'a souligné Hudson, aurait été de disposer l'objet après usage.

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
            }
} 
0
répondu Abhishek Poojary 2018-07-28 10:05:38