2010-09-28 10 views
2

J'ai quelques applications en cours d'exécution dans des processus distincts qui écrivent chacun à un document xml central sur le disque dur. J'utilise un mutex nommé pour synchroniser l'accès au dossier - mais obtenir l'exception suivante souvent:File.Exists() et la synchronisation d'accès aux fichiers à travers les processus

System.IO.IOException: The requested operation cannot be performed on a file with a user-mapped section open. 

je réalisais que je fais appel à la méthode File.Exists() avant d'obtenir un verrou sur le mutex, est-il possible que cela pourrait être la cause?

Plus simplement, quelqu'un peut-il confirmer si cette méthode fait une lecture sur le fichier pour vérifier si elle existe? Je me demande si je dois verrouiller le mutex avant de vérifier si le fichier est présent. J'ai vérifié qu'il n'y avait pas de logiciel AV en cours d'exécution, car cela semblait être commun avec cette exception.

exemple rugueux du code actuel:

private bool UpdateFile(string Text) 
{ 
    if (!File.Exists(@"C:\FileName.xml")) 
    return false; 
    else 
    { 
    using (Mutex mutex = new Mutex(false, "ExampleMutexName")) 
    { 
     mutex.WaitOne(); 
     //Write to the file 
     mutex.ReleaseMutex(); 
    } 
    return true; 
    } 
} 

EDIT: Je n'utilisais pas un mutex global, car tout se passe à l'intérieur du même compte utilisateur - si je croyais un mutex local serait bien. Cependant, l'un des processus que je commence est avec l'emprunt d'identité - c'est pourquoi je DEVRAIS avoir utilisé un mutex global. Mon erreur était juste de penser que tout fonctionne avec le même compte d'utilisateur et serait bien.

+0

Je doute fortement que votre code actuel grossier contribue à cette erreur - il est ailleurs ... – t0mm13b

+0

En regardant la trace de la pile de l'exception vous dira quelle fonction dans votre code l'a causé. –

+0

Notez que votre nom de mutex doit commencer par "Global \" afin qu'il soit globalement visible dans toutes les sessions Windows en cours (voir la section de remarque ici: http://msdn.microsoft.com/en-us/library/f55ddskf.aspx –

Répondre

1
  1. File.Exists renvoie la valeur false en cas d'erreur et ne lance pas. Il ne lit pas le contenu du fichier s'il vérifie les autorisations de lecture.
  2. Cela n'a pas beaucoup de sens de vérifier si le fichier existe avant de verrouiller le mutex, car il en résulte des conditions de course. Un fichier pourrait être retiré par quelqu'un d'autre après votre vérification et avant que votre mutex ne soit verrouillé.
  3. Le mutex que vous utilisez n'est pas global, il n'y a donc aucune garantie qu'une autre application du même type ne modifie pas le fichier en parallèle. Même si c'était global, il y a un problème quand une application n'honore pas le verrou. La meilleure façon d'y aller est d'utiliser le verrouillage de fichier. Voir Lock et Unlock.
  4. L'erreur que vous voyez signifie essentiellement que le fichier est ouvert par un autre processus, ce qui suggère une région mappée en mémoire.

P.S .: Il serait également intéressant d'exclure ce fichier du service d'indexation.

+0

Pour ajouter à la réponse de Vlad, il y a un autre message avec la même erreur. était avec le fichier étant verrouillé par un autre processus, voir cet article pour référence supplémentaire: http://stackoverflow.com/questions/1302698/system-io-exception-error-the-requested-operation-cannot-be-performed-on -a-file –

+0

Je comprends les conditions de course en appelant 'File.Exists()' avant de verrouiller le mutex. Je comprends que atomiquement, un autre processus/thread peut avoir modifié le fichier. Avec même dans cette seconde, si le fichier n'était pas présent - il n'y avait pas besoin de mettre à jour le fichier.Cela pourrait être plutôt laxiste - c'est pourquoi je suis retourné faux et a continué. Je crois comprendre qu'un mutex global était une session croisée. Ces applications fonctionnent avec dans un seul compte d'utilisateur. Dans lequel je ne pensais pas que cela importait - ce pourrait être le problème. – kmfk