2010-09-17 13 views
9

J'ai un programme qui fait à peu près ceci:fichier est utilisé par un autre processus

  1. ouvrir un fichier à lire.
  2. fermer le fichier
  3. Démarrez un gestionnaire de fichiers pour surveiller les modifications apportées au fichier.
  4. Dès qu'un changement est détecté, le EnableRaisingEvents de Filewatcher drapeau est mis à faux et le processus se répète à l'étape 1.

Le problème est, après avoir à l'étape 4 à l'étape 1, il ne peut pas lire la fichier indiquant qu'il est utilisé par un autre processus.

Erreur Je reçois:

Exception non gérée: System.IO.IOException: Le processus ne peut pas accéder au fichier « c: \ test.xml » parce qu'il est utilisé par un autre processus.

Ce qui ne va pas? est-ce que le lecteur de l'étape 1 de mon programme a toujours le fichier ouvert, ou est-ce un processus entièrement différent accédant au fichier, ou est-ce que filewatcher est toujours en train de regarder le fichier après avoir passé à l'étape 1 de 4?

+0

Pouvez-vous envoyer votre code. Cela peut nous aider à répondre à votre question. – klabranche

+1

Publier du code. Aidez-nous à vous aider. –

+1

Le code est un peu énorme et confidentiel, car il est pour une firme financière, mais je vais voir si je peux le faire en toute sécurité et le poster. – xbonez

Répondre

8

Si votre code est similaire à ceci:

[STAThread] 
static void Main(string[] args) 
{ 
    string file = "temp.txt"; 
    ReadFile(file); 
    FileSystemWatcher fswatcher = new FileSystemWatcher(".\\"); 
    fswatcher.Changed += delegate(object sender, FileSystemEventArgs e) 
          { 
           ReadFile(e.FullPath); 
          }; 
    while (true) 
    { 
     fswatcher.WaitForChanged(WatcherChangeTypes.Changed); 
    } 
} 
private static void ReadFile(string file) 
{ 
    Stream stream = File.OpenRead(file); 
    StreamReader streamReader = new StreamReader(stream); 
    string str = streamReader.ReadToEnd(); 
    MessageBox.Show(str); 
    streamReader.Close(); 
    stream.Close(); 
} 

Si vous modifiez le fichier via le bloc-notes, puis, lorsque vous cliquez sur le bouton Enregistrer, il garde le fichier ouvert, tout comme si vous venez de fermer le programme et cliquez sur Enregistrer ne le fait pas. Je ne sais pas s'il s'agit d'un bug ou d'une fonctionnalité non documentée du bloc-notes, mais cela pourrait être votre problème.Une façon de résoudre ce problème consiste à:

Dans votre délégué anonyme, ou partout où vous exécutez l'appel à ReadFile() appel Thread.Sleep(1000), pour que le programme attendez avant de lire le fichier et votre code devrait fonctionner correctement.

+1

Thread.Sleep semble avoir résolu le problème. Merci! – xbonez

+0

@xbonez: ce code fonctionne bien pour moi, même sans Thread.Sleep() '. (J'ai changé 'MessageBox.Show' en' Console.WriteLine') Cependant, j'utiliserais toujours une instruction 'using'. – JohnB

+0

Après avoir joué un peu plus, j'ai découvert que si deux instances de ce programme regardaient le même fichier, lorsque je clique sur "Enregistrer" dans le Bloc-notes, j'obtiens cette erreur de l'une des instances (l'autre continue): 'Le processus ne peut pas accéder au fichier 'c: \ fichier.txt' car il est utilisé par un autre processus. ' – JohnB

4

Vous pouvez utiliser un outil comme Process Explorer de http://www.sysinternals.com pour voir qui a la poignée ouverte au processus

Le fichier est très probablement maintenu ouvert par tout ce qui a causé la notification de changement au feu en premier lieu.

+0

+1 pour l'explorateur de processus. – NotMe

0

Il y a un certain nombre de choses qui pourraient se passer. Tout d'abord, assurez-vous de disposer correctement du programme d'écriture de fichier (fermer n'est pas assez bon) en utilisant la clause using autour de tout ce qui implémente IDisposable. Deuxièmement, si vous lisez simplement, assurez-vous que les drapeaux corrects sont définis lors de l'ouverture du fichier. Pour aller plus loin, il serait utile que vous fournissiez un bloc de code qui montre comment vous avez accompli cela; en particulier autour de la lecture du fichier

+0

+1: Je suis d'accord, utilisez les instructions 'using' – JohnB

3

Remarque: même si "fichier.txt" est ouvert dans le Bloc-notes, ce code fonctionne toujours, car il ouvre en lecture.

using System; 
using System.IO; 

class Program 
{ 
    static void Main(string[] args) 
    { 
    ReadFromFile(@"C:\file.txt"); 
    Console.ReadLine(); 
    } 

    static void ReadFromFile(string filename) 
    { 
    string line; 
    using (StreamReader sr = File.OpenText(filename)) 
    { 
     line = sr.ReadLine(); 
     while (line != null) 
     { 
     Console.WriteLine(str); 
     line = sr.ReadLine(); 
     } 
     sr.Close(); 
    } 
    } 
} 

Ou tout simplement:

string text = System.IO.File.ReadAllText(@"C:\file.txt");

3

À côté des autres réponses il est possible que lorsque FileWatcher réagit, il n'est pas encore fermé par cette application. À l'étape 1, essayez de ne pas échouer immédiatement, mais essayez plusieurs tentatives avec un petit délai.

0

Vous pouvez utiliser cet utilitaire MS openfiles pour obtenir la liste des fichiers ouverts et comprendre qui a ouvert le fichier.

openfiles /query 

Permet également de déconnecter les fichiers ouverts par les utilisateurs du réseau.

openfiles /disconnect /id XXXX 

Si vous voulez l'utiliser pour PC local, vous devez définir gérer des objets Liste indicateur global:

openfiles /local on 

Suivez les link pour obtenir plus de détails.

Questions connexes