web-dev-qa-db-fra.com

System.IO.IOException: 'Le processus ne peut pas accéder au fichier' @ .txt 'car il est utilisé par un autre processus.'

Je suis nouveau en programmation et j'ai une question. Si j'ai deux fonctions, l'une crée un fichier texte dans lequel elle écrit, tandis que l'autre ouvre le même fichier texte et la lit.

L'erreur que je reçois est: 

System.IO.IOException: 'Le processus ne peut pas accéder au fichier' @ .txt ' Car il est utilisé par un autre processus.'

J'ai essayé de régler des minuteries séparées pour chacune des fonctions, mais cela ne fonctionne toujours pas. Je pense que le meilleur moyen serait que la fonction deux ne commence pas avant la fin de la fonction un.

Pouvez-vous m'aider à atteindre cet objectif? Merci beaucoup! Mike

Code source:

public Form1() {
    InitializeComponent();
    System.Timers.Timer timerButtona1 = new System.Timers.Timer();
    timerButtona1.Elapsed += new ElapsedEventHandler(tickTimera1);
    timerButtona1.Interval = 3003;
    timerButtona1.Enabled = true;
}

private async void tickTimera1(object source, ElapsedEventArgs e) {
    function1();
    function2();
}

void function1() {
    List<string> linki = new List<string>();

    linki.Add("https://link1.net/");
    linki.Add("https://link2.net/");
    linki.Add("https://link3.net/");

    List<string> fileNames = new List<string>();

    fileNames.Add("name1");
    fileNames.Add("name2");
    fileNames.Add("name3");

    for (int x = 0; x < fileNames.Count; x++) {
        GET(linki[x], fileNames[x]);
        //System.Threading.Thread.Sleep(6000);
    }
}

async void GET(string link, string fileName) {
    var ODGOVOR = await PRENOS_PODATKOV.GetStringAsync(link);
    File.WriteAllText(@"C:\Users\...\" + fileName + ".txt", ODGOVOR);
}

void function2() {
    string originalText = File.ReadAllText(@"C:\Users\...\fileName.txt", Encoding.Default);
    dynamic modifiedText = JsonConvert.DeserializeObject(originalText);
    //then i then i read from the same text files and use some data from it..
}
2
Mike

Vous devrez fermer le fichier après l'avoir édité.

var myFile = File.Create(myPath);
//myPath = "C:\file.txt"
myFile.Close();
//closes the text file for eg. file.txt
//You can write your reading functions now..

Après l'avoir fermé, vous pouvez encore l'utiliser (pour la lecture)

4
rshah4u

après avoir écrit votre fichier texte, fermez-le avant de passer à votre deuxième fonction:

var myFile = File.Create(myPath);
//some other operations here like writing into the text file
myFile.Close(); //close text file
//call your 2nd function here

Juste pour élaborer:

public void Start() {
    string filename = "myFile.txt";
    CreateFile(filename); //call your create textfile method
    ReadFile(filename); //call read file method
}

public void CreateFile(string filename) {
    var myFile = File.Create(myPath); //create file
    //some other operations here like writing into the text file
    myFile.Close(); //close text file
}

public void ReadFile(string filename) {
    string text;
    var fileStream = new FileStream(filename, FileMode.Open, 
    FileAccess.Read); //open text file
    //vvv read text file (or however you implement it like here vvv
    using (var streamReader = new StreamReader(fileStream, Encoding.UTF8))
    {
        text = streamReader.ReadToEnd();
    }
    //finally, close text file
    fileStream.Close();
}

Le fait est que vous devez fermer FileStream après avoir terminé toute opération sur votre fichier. Vous pouvez le faire via myFileStream.Close().

De plus, File.Create(filename) renvoie un objet FileStream que vous pouvez ensuite Close().

3
Geoman Yabes

En réalité, il n’ya pas de problème de fermeture/élimination du flux, File.WriteAllText et File.ReadAllText le font en interne.

Le problème est dû à une mauvaise utilisation du modèle async/await. GET est asynchrone, mais jamais attendu. Le code function1 se termine et passe à function2 avant que tout le contenu ne soit réellement écrit dans le fichier.

La manière dont il est écrit GET n’est pas attendue car c’est async void qui ne devrait jamais être utilisé à moins que vous n’ayez affaire à un événement ou que vous sachiez vraiment ce que vous faites.

Donc, supprimez complètement l'utilisation de async/await ou restez async complètement:

  1. Changer GET pour être en attente:

    async Task GET(string link, string fileName)
    
  2. attendez-le dans le maintenant async function1:

    async Task function1()
    {
        ...
        for (int x = 0; x < fileNames.Count; x++)
        {
            await GET(linki[x], fileNames[x]);
            //System.Threading.Thread.Sleep(6000);
        }
        ...
    
  3. wait function1 dans l'événement Elapsed:

    private async void tickTimera1(object source, ElapsedEventArgs e)
    {
        await function1();
        function2();
    }
    
1
Ofir Winegarten

Le problème est parfois que les verrous de fichiers ne sont pas libérés immédiatement après leur fermeture. 

Vous pouvez essayer de lancer une boucle pour lire le fichier. Dans la boucle, placez une instruction try catch et, si le fichier est lu, coupez-le. Sinon, attendez quelques millisecondes et essayez de relire le fichier:

string originalText = null;
while (true)
{
    try
    {
        originalText = File.ReadAllText(@"C:\Users\...\fileName.txt", Encoding.Default);
        break;
    }
    catch 
    { 
        System.Threading.Thread.Sleep(100);
    }
}
0
Alexander Higgins