IOException: het proces heeft geen toegang tot het bestand ‘bestandspad’ omdat het door een ander proces wordt gebruikt

Ik heb wat code en wanneer het wordt uitgevoerd, genereert het een IOExceptionen zegt dat

Het proces heeft geen toegang tot het bestand ‘bestandsnaam’ omdat het wordt gebruikt door
een ander proces

Wat betekent dit en wat kan ik eraan doen?


Antwoord 1, autoriteit 100%

Wat is de oorzaak?

De foutmelding is vrij duidelijk: je probeert toegang te krijgen tot een bestand en het is niet toegankelijk omdat een ander proces (of zelfs hetzelfde proces) er iets mee doet (en delen niet toestond).

Foutopsporing

Het is misschien vrij eenvoudig op te lossen (of behoorlijk moeilijk te begrijpen), afhankelijk van uw specifieke scenario. Laten we eens kijken.

Uw proces is de enige die toegang heeft tot dat bestand
U weet zeker dat het andereproces uw eigen proces is. Als je weet dat je dat bestand in een ander deel van je programma opent, moet je allereerst controleren of je de bestandshandle na elk gebruik goed sluit. Hier is een voorbeeld van code met deze 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

Gelukkig implementeert FileStreamIDisposable, dus het is gemakkelijk om al je code in een using-instructie te stoppen:

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

Dit patroon zorgt er ook voor dat het bestand niet open blijft staan in geval van uitzonderingen (het kan de reden zijn dat het bestand in gebruik is: er is iets misgegaan en niemand heeft het gesloten; zie dit berichtvoor een voorbeeld).

Als alles in orde lijkt (je weet zeker dat je altijd elk bestand dat je opent sluit, zelfs in geval van uitzonderingen) en je hebt meerdere werkende threads, dan heb je twee opties: herwerk je code om de toegang tot bestanden te serialiseren (niet altijd mogelijk en niet altijd gewenst) of pas een patroon voor opnieuw proberentoe. Het is een vrij algemeen patroon voor I/O-bewerkingen: je probeert iets te doen en in het geval van een fout wacht je en probeer je het opnieuw (heb je je afgevraagd waarom bijvoorbeeld Windows Shell enige tijd nodig heeft om je te informeren dat een bestand in gebruik is en kan niet worden verwijderd?). In C# is het vrij eenvoudig te implementeren (zie ook betere voorbeelden over disk I/O, netwerkenen databasetoegang).

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

Let op een veelvoorkomende fout die we heel vaak zien op StackOverflow:

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

In dit geval zal ReadAllText()mislukken omdat het bestand in gebruik is (File.Open()in de regel ervoor). Het bestand vooraf openen is niet alleen onnodig, maar ook verkeerd. Hetzelfde geldt voor alle File-functies die geen handleteruggeven aan het bestand waarmee u werkt: File.ReadAllText(), File.WriteAllText(), File.ReadAllLines(), File.WriteAllLines()en anderen (zoals File.AppendAllXyz()functies) zullen het bestand allemaal vanzelf openen en sluiten.

Uw proces is niet het enige dat toegang heeft tot dat bestand
Als uw proces niet het enige is dat toegang heeft tot dat bestand, kan interactie moeilijker zijn. Een patroon opnieuw proberenzal helpen (als het bestand door niemand anders zou moeten worden geopend, maar dat is het wel, dan heeft u een hulpprogramma zoals Process Explorer nodig om te controleren wiewat).

Manieren om te vermijden

Gebruik indien van toepassing altijd gebruikinstructies om bestanden te openen. Zoals gezegd in de vorige paragraaf, zal het je actief helpen om veel voorkomende fouten te voorkomen (zie dit berichtvoor een voorbeeld op hoe het niet te gebruiken).

Probeer indien mogelijk te beslissen wie toegang heeft tot een specifiek bestand en centraliseer de toegang via een paar bekende methoden. Als u bijvoorbeeld een gegevensbestand hebt waarin uw programma leest en schrijft, moet u alle I/O-code in een enkele klasse plaatsen. Het zal debug gemakkelijker maken (omdat je daar altijd een onderbrekingspunt kunt plaatsen en zien wie wat doet) en het zal ook een synchronisatiepunt zijn (indien nodig) voor meervoudige toegang.

Vergeet niet dat I/O-bewerkingen altijd kunnen mislukken, een veelvoorkomend voorbeeld is dit:

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

Als iemandhet bestand verwijdert na File.Exists()maar vóór File.Delete(), dan wordt een IOExceptionop een plaats waar u zich onterecht veilig kunt voelen.

Pas waar mogelijk een patroon voor opnieuw proberentoe, en als u FileSystemWatchergebruikt, overweeg dan om actie uit te stellen (omdat u een melding krijgt, maar een toepassing kan nog steeds uitsluitend met dat bestand werken).

Geavanceerde scenario’s
Het is niet altijd zo eenvoudig, dus het kan zijn dat u de toegang met iemand anders moet delen. Als je bijvoorbeeld vanaf het begin leest en tot het einde schrijft, heb je ten minste twee opties.

1) deel dezelfde FileStreammet de juiste synchronisatiefuncties (omdat het niet thread-safeis). Zie diten dita>berichten voor een voorbeeld.

2) gebruik FileShareopsomming om het besturingssysteem te instrueren om andere processen (of andere delen van uw eigen proces) gelijktijdig toegang te geven tot hetzelfde bestand.

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

In dit voorbeeld toonde ik hoe ik een bestand opent voor schrijven en delen voor lezen; Houd er rekening mee dat bij het lezen en schrijven van overlappingen, het resulteert in ongedefinieerde of ongeldige gegevens. Het is een situatie die moet worden afgehandeld bij het lezen. Merk ook op dat dit geen toegang geeft tot de streamThread-Safe, zodat dit object niet met meerdere threads kan worden gedeeld, tenzij de toegang op een of andere manier wordt gesynchroniseerd (zie vorige links). Er zijn andere delen van delen beschikbaar en ze openen complexere scenario’s. Raadpleeg MSDN voor meer details.

In het algemeen N Processen kunnen uit elkaar lezen vanuit hetzelfde bestand, maar slechts één zou moeten schrijven, in een gecontroleerd scenario, kunt u zelfs gelijkgeschreven geschriften inschakelen, maar dit kan hierin niet worden gegeneraliseerd Antwoord.

Is het mogelijk om ontgrendelen een bestand dat wordt gebruikt door een ander proces? Het is niet altijd veilig en niet zo eenvoudig, maar ja, Het is mogelijk .


2, Autoriteit 11%

Gebruik Fileshare Vast mijn nummer van het openingsbestand vast, zelfs als deze wordt geopend door een ander proces.

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

3, Autoriteit 4%

had een probleem tijdens het uploaden van een afbeelding en kon het niet verwijderen en een oplossing gevonden. GL HF

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

4

Ik heb deze fout omdat ik File.Move mee bezig was om een ​​bestand pad zonder een bestandsnaam, noodzaak om het volledige pad in de bestemming op te geven.


5

Zoals andere antwoorden in deze thread hebben opgemerkt, deze fout moet je zorgvuldig te inspecteren de code, om te begrijpen waar het bestand wordt steeds geblokkeerd. Lossen

In mijn geval, ik was het verzenden van het bestand als een e-mailbijlage voor het uitvoeren van de verhuizing operatie.

Dus de file afgesloten kregen voor een paar seconden tot SMTP-client klaar is het versturen van de e-mail.

De oplossing die ik aangenomen was om verplaatst u het bestand eerst, en stuur de e-mail. Dit loste het probleem voor mij.

Een andere mogelijke oplossing, zoals eerder door Hudson, geweest zou zijn om het object te verwijderen na gebruik.

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

6

Probleem

men binden open bestand System.IO.File.Open(path, FileMode)met deze methode en wil een gedeelde toegang bestand maar

Als u lezen documentatie van System.IO.File.Open (pad, FileMode) wordt expliciet te zeggen zijn niet Toestaan ​​delen

oplossing

Gebruik u moet andere override gebruiken met fileshare

using FileStream fs = System.IO.File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);

met FileShare.Read


Antwoord 7

Ik had het volgende scenario dat dezelfde fout veroorzaakte:

  • Bestanden uploaden naar de server
  • Verwijder vervolgens de oude bestanden nadat ze zijn geüpload

De meeste bestanden waren klein van formaat, maar een paar waren groot, en een poging om deze te verwijderen resulteerde in de fout geen toegang tot bestand.

Het was niet gemakkelijk te vinden, maar de oplossing was zo simpel als Wachten“op de taak om de uitvoering te voltooien”:

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

Antwoord 8

Ik had dit probleem en het is opgelost door de onderstaande code te volgen

var _path=MyFile.FileName;
using (var stream = new FileStream
    (_path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
  { 
    // Your Code! ;
  }

Antwoord 9

Mijn onderstaande code lost dit probleem op, maar ik stel voor
Allereerst moet u begrijpen waardoor dit probleem wordt veroorzaakt en de oplossing proberen die u kunt vinden door de code te wijzigen

Ik kan een andere manier geven om dit probleem op te lossen, maar een betere oplossing is om uw coderingsstructuur te controleren en te proberen te analyseren waardoor dit gebeurt. Als u geen oplossing vindt, kunt u deze code hieronder gebruiken

try{
Start:
///Put your file access code here
}catch (Exception ex)
 {
//by anyway you need to handle this error with below code
   if (ex.Message.StartsWith("The process cannot access the file"))
    {
         //Wait for 5 seconds to free that file and then start execution again
         Thread.Sleep(5000);
         goto Start;
    }
 }

Other episodes