IOException: Der process kann nicht auf den Dateipfad zugreifen, da er von einem anderen process verwendet wird

Ich habe etwas Code und wenn es ausgeführt wird, IOException es eine IOException und sagt das

Der process kann nicht auf die Datei “Dateiname” zugreifen, da sie von einem anderen process verwendet wird

Was bedeutet das und was kann ich dagegen tun?

   

Was ist die Ursache?

Die Fehlermeldung ist ziemlich klar: Sie versuchen, auf eine Datei zuzugreifen, und sie ist nicht zugänglich, weil ein anderer process (oder sogar derselbe process) etwas damit macht (und keine Freigabe erlaubt).

Debuggen

Je nachdem, welches Szenario Sie haben, kann es ziemlich einfach zu lösen sein (oder ziemlich schwer zu verstehen). Lass uns welche sehen.

Ihr process ist der einzige, der auf diese Datei zugreift
Sie sind sicher, dass der andere process Ihr eigener process ist. Wenn Sie wissen, dass Sie diese Datei in einem anderen Teil Ihres Programms öffnen, müssen Sie zuerst überprüfen, ob Sie den Dateigriff nach jeder Verwendung ordnungsgemäß geschlossen haben. Hier ist ein Beispiel für Code mit diesem Fehler:

 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 

Glücklicherweise implementiert IDisposable , sodass es einfach ist, den gesamten Code in eine using statement zu IDisposable :

 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 

Dieses Muster stellt auch sicher, dass die Datei im Falle von Ausnahmen nicht offen gelassen wird (dies könnte der Grund sein, warum die Datei verwendet wird: etwas ist schief gelaufen und niemand hat es geschlossen; siehe diesen Beitrag als Beispiel).

Wenn alles in Ordnung ist (Sie sind sicher, dass Sie immer alle geöffneten Dateien schließen, auch wenn es Ausnahmen gibt) und Sie mehrere Arbeitsthreads haben, haben Sie zwei Möglichkeiten: Ihren Code so zu bearbeiten, dass der Dateizugriff serialisiert wird (nicht immer machbar und nicht immer) gewünscht) oder ein Wiederholungsmuster anwenden. Es ist ein ziemlich häufiges Muster für I / O-Vorgänge: Sie versuchen, etwas zu tun, und im Fehlerfall warten Sie und versuchen es erneut (haben Sie sich gefragt, warum beispielsweise Windows Shell einige Zeit benötigt, um Sie darüber zu informieren, dass eine Datei verwendet wird) und kann nicht gelöscht werden?). In C # ist es ziemlich einfach zu implementieren (siehe auch bessere Beispiele zu Festplatten-I / O , Netzwerk- und databasezugriff ).

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

Bitte beachten Sie einen häufigen Fehler, den wir sehr oft auf StackOverflow sehen:

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

In diesem Fall wird ReadAllText() fehlschlagen, weil die Datei verwendet wird ( File.Open() in der Zeile davor). Es ist nicht nur unnötig, die Datei vorher zu öffnen, sondern auch falsch. Dasselbe gilt für alle File.ReadAllText() , die kein Handle für die Datei zurückgeben, mit der Sie arbeiten: File.ReadAllText() , File.WriteAllText() , File.ReadAllLines() , File.WriteAllLines() und andere (wie File.AppendAllXyz() functionen öffnen und schließen die Datei selbst.

Ihr process ist nicht der einzige, der auf diese Datei zugreift
Wenn Ihr process nicht der einzige ist, der auf diese Datei zugreift, kann die Interaktion schwieriger sein. Ein Wiederholungsmuster wird helfen (wenn die Datei nicht von jemand anderem geöffnet werden sollte, aber es ist, dann brauchen Sie ein Dienstprogramm wie Process Explorer, um zu überprüfen, wer was macht ).

Wege zu vermeiden

Verwenden Sie gegebenenfalls immer statementen, um Dateien zu öffnen. Wie im vorherigen Absatz erwähnt, wird es Ihnen aktiv dabei helfen, viele häufige Fehler zu vermeiden (siehe diesen Beitrag als Beispiel, wie Sie ihn nicht verwenden können ).

Versuchen Sie nach Möglichkeit zu entscheiden, wer Zugriff auf eine bestimmte Datei hat und zentralisieren Sie den Zugriff über einige bekannte Methoden. Wenn Sie beispielsweise eine Datendatei haben, in der Ihr Programm liest und schreibt, sollten Sie den gesamten E / A-Code in eine einzige class schreiben. Es erleichtert das Debuggen (weil Sie dort immer einen Haltepunkt setzen können und sehen, wer was macht) und auch ein Synchronisationspunkt (falls erforderlich) für den Mehrfachzugriff.

Vergessen Sie nicht, dass E / A-Vorgänge immer fehlschlagen können. Ein typisches Beispiel ist dies:

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

Wenn jemand die Datei nach File.Exists() aber vor File.Delete() löscht, wird eine IOException an eine Stelle IOException an der Sie sich fälschlicherweise sicher fühlen.

Wann immer es möglich ist, wenden Sie ein Wiederholungsmuster an , und wenn Sie FileSystemWatcher , ziehen Sie eine Verschiebung der Aktion in Betracht (weil Sie benachrichtigt werden, aber eine Anwendung möglicherweise immer noch ausschließlich mit dieser Datei arbeitet).

Erweiterte Szenarien
Es ist nicht immer so einfach, daher müssen Sie möglicherweise den Zugriff mit jemand anderem teilen. Wenn Sie zum Beispiel von Anfang an lesen und bis zum Ende schreiben, haben Sie mindestens zwei Optionen.

1) teilen Sie den gleichen FileStream mit den richtigen Synchronisationsfunktionen (weil es nicht threadsicher ist ). Sehen Sie dies und dieses Posts für ein Beispiel.

2) Verwenden Sie die FileShare Enumeration, um OS anzuweisen, anderen processen (oder anderen Teilen Ihres eigenen processes) den gleichzeitigen Zugriff auf dieselbe Datei zu erlauben.

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

In diesem Beispiel habe ich gezeigt, wie man eine Datei zum Schreiben und zum Lesen öffnet; Bitte beachten Sie, dass beim Lesen und Schreiben von Überlappungen nicht definierte oder ungültige Daten entstehen. Es ist eine Situation, die beim Lesen behandelt werden muss. Beachten Sie außerdem, dass dies den Zugriff auf den Thread nicht threadsicher macht. Daher kann dieses Objekt nicht mit mehreren Threads geteilt werden, es sei denn, der Zugriff wird irgendwie synchronisiert (siehe vorherige Links). Andere Freigabeoptionen sind verfügbar und sie öffnen komplexere Szenarien. Weitere Informationen finden Sie in MSDN .

Im Allgemeinen können N processe aus derselben Datei alle zusammen lesen, aber nur einer sollte schreiben, in einem kontrollierten Szenario können Sie sogar gleichzeitige Schriften aktivieren, aber dies kann nicht in wenigen Textabsätzen innerhalb dieser Antwort verallgemeinert werden.

Ist es möglich, eine Datei freizugeben , die von einem anderen process verwendet wird? Es ist nicht immer sicher und nicht so einfach, aber ja, es ist möglich .

Hatte beim Hochladen eines Bildes ein Problem und konnte es nicht löschen und eine Lösung finden. Viel Glück und Viel Spaß

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

Die Verwendung von FileShare behebt mein Problem beim Öffnen der Datei, selbst wenn sie von einem anderen process geöffnet wird.

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

Ich habe diesen Fehler, weil ich File.Move zu einem Dateipfad ohne einen Dateinamen machte, müssen den vollständigen Pfad im Ziel angeben.

Ich hatte das folgende Szenario, das den gleichen Fehler verursachte:

  • Laden Sie Dateien auf den Server hoch
  • Dann werden die alten Dateien nach dem Hochladen gelöscht

Die meisten Dateien waren klein, einige waren jedoch groß, und der Versuch, diese zu löschen, führte dazu, dass auf Dateierrors nicht zugegriffen werden konnte.

Es war nicht einfach zu finden, aber die Lösung war so einfach wie Warten auf die Ausführung der Aufgabe:

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

Wie andere Antworten in diesem Thread darauf hingewiesen haben, müssen Sie, um diesen Fehler zu beheben, den Code sorgfältig untersuchen, um zu verstehen, wo die Datei gesperrt wird.

In meinem Fall sendete ich die Datei als E-Mail-Anhang, bevor ich den Verschiebevorgang ausführte.

Die Datei wurde für einige Sekunden gesperrt, bis der SMTP-Client die E-Mail versandt hat.

Die Lösung, die ich annahm, bestand darin , zuerst die Datei zu verschieben und dann die E-Mail zu senden. Das hat das Problem für mich getriggers.

Eine andere mögliche Lösung, wie bereits von Hudson erwähnt, wäre gewesen, das Objekt nach der Verwendung zu entsorgen.

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

Gehen Sie zum Dateipfad und löschen Sie es und starten Sie dann erneut Android Studio möglicherweise Konflikt zwischen zwei Dateien