2010-11-29 4 views
5

Puis-je utiliser le constructeur FileStream pour m'assurer qu'un seul processus accède à un fichier à la fois? Est-ce que le code suivant fonctionnera?Puis-je utiliser FileStream pour implémenter un verrouillage de fichier?

public static IDisposable AcquireFileLock() { 
    IDisposable lockObj; 
    do { 
     // spinlock - continually try to open the file until we succeed 
     lockObj = TryOpenLockFile(); 

     // sleep for a little bit to let someone else have a go if we fail 
     if (lockObj == null) Thread.Sleep(100); 
    } 
    while (lockObj == null); 

    return lockObj; 
} 

private static FileStream TryOpenLockFile() { 
    try { 
     return new FileStream(s_LockFileName, FileMode.Create, FileAccess.Read, FileShare.None); 
    } 
    catch (IOException) { 
     return null; 
    } 
} 

En particulier, le comportement avec FileMode.Create WRT atomique autres processus? Y a-t-il autre chose que je devrais utiliser?

EDIT: pour être plus précis, il s'agit de Microsoft CLR utilisant des fichiers locaux sur une seule machine.

+0

Cela semble bon! Mais qui nettoie le fichier de verrouillage? Il n'y a probablement aucun besoin fonctionnel de le faire puisque l'invocation de ctor 'FileStream' écrase toujours le fichier de verrou existant. –

+0

Pour le nettoyage, je pourrais toujours 'essayer {File.Delete (...)}' et ignorer toutes les exceptions (car cela signifie qu'un autre processus a pris le verrou pendant ce temps) ... – thecoop

Répondre

2

Cela fera ce que vous voulez. FileShare.None est la partie importante. Si toutes les applications d'écriture sont sur le même ordinateur, vous pouvez également utiliser un named Mutex pour atteindre le même objectif sans avoir besoin d'un fichier physique, ou pour médiatiser l'accès aux fichiers si vous ne vous souciez pas de savoir qui écrit dans le fichier (juste que les écritures ne sont pas concurrentes). Cela pourrait vous éviter d'avoir à rouvrir le fichier à chaque fois, et fournir une sémantique de blocage à la place de votre boucle Sleep (meilleure perf).

Notez que tout processus peut s'accroupir sur votre fichier (Mutex) si le nom n'est pas traité comme un secret, c'est-à-dire des informations qui doivent être conservées en toute sécurité.

+2

Un Mutex ne fonctionne que sur le même ordinateur. Les verrous de fichiers fonctionnent sur un réseau. – Gabe

+0

@Gabe - ce n'est pas clair quel est le cas d'utilisation, mais vous avez raison –

1

Cela fonctionne, étant donné les mises en garde suivantes:

  • Vous êtes sur Windows (Linux via Mono, cela ne tient pas puisque les verrous de fichier sont de conseil, de sorte que votre méthode réussit toujours)
  • vous accédez à un fichier local (SMB travaillera également probablement, mais NFS ou WebDAV presque certainement pas)
  • attraper IOException est probablement trop large, vous devez vérifier spécifiquement qu'il a échoué en raison d'une violation de partage
+0

IOException est celui qui est levé lorsque le fichier est déjà verrouillé, je ne peux rien saisir de plus spécifique:/ – thecoop

+0

Vous pouvez consulter le HResult pour voir s'il a un code d'erreur Win32, ou à défaut, vous pouvez (pouah) vérifier le texte du message –

Questions connexes