2013-05-28 1 views
0

J'ai une application multi-thread. Mon problème est que parfois je reçois une erreur comme le programme ne peut pas accéder à un fichier car il est utilisé par autre chose (autre partie de l'application).La meilleure solution pour résoudre le fichier ne peut pas accéder à l'erreur

En ce moment, j'ai attrapé l'exception et répété la tâche après un délai de 100ms.

Cela fonctionne comme l'application n'ouvre pas les fichiers si souvent et il est ouvert les fichiers juste pour une courte période.

Bien que je ne suis pas heureux avec cette solution car elle est moche, et il peut encore aller mal.

Y a-t-il de bons moyens de résoudre ce problème? S'il n'y a pas de réponse facile et que vous avez besoin de plus d'informations sur l'application (quels fichiers, pourquoi je pourrais accéder en même temps) je peux répondre, j'essaie juste de garder la question simple, et générique.

Cordialement Daniel

EDIT:

je compose quelque chose de rapide, ce que vous en pensez au sujet de cette solution, ce n'est pas la plus générique, mais n'a pas eu une meilleure idée tout à l'heure:

Lorsque le programme essaie d'écrire dans le fichier, vérifiez s'il est utilisé ou non. Si elle est utilisée, collecter des données dans la mémoire, dès que l'application veut réécrire dans le fichier et le fichier est libre insérer dans toutes les données.

Ce n'est toujours pas le meilleur, mais cela pourrait donner plus d'idées.

+0

Comment ouvrir les fichiers? Pouvez-vous utiliser le paramètre 'FileShare.ReadWrite' dans le constructeur' FileStream'? Voir http://msdn.microsoft.com/en-us/library/5h0z48dh.aspx – Gabe

+0

question connexe http://stackoverflow.com/questions/3808474/whats-the-right-pattern-for-waiting-on-a -file-lock-to-be-released – PeskyGnat

+0

@Gabe J'utilise StreamWriter. Quand je lis le fichier j'ai besoin de lire toutes les données jusqu'à la fin, quand j'insère j'insère des données à la fin. Ne sera-t-il pas doggy (perdre des données) si je partage le fichier? – Daniel

Répondre

3

Étant donné que votre application lit et écrit le fichier, tout ce que vous devez faire est de garder une trace des fichiers utilisés par votre application. Conservez un dictionnaire de R/W locks avec un nom de fichier. Lorsque vous allez accéder à un fichier, retirez le verrou approprié.

Voilà comment vous pouvez coder:

Dictionary<string, ReaderWriterLockSlim> lockDict = new Dictionary<string, ReaderWriterLockSlim>(); 

ReaderWriterLockSlim LockFile(string filename, bool readOnly) 
{ 
    var fullPath = System.IO.Path.GetFullPath(filename); 
    ReaderWriterLockSlim myLock; 
    // lock the dictionary while we're accessing it 
    lock (lockDict) 
    { 
     if (!lockDict.TryGetValue(fullPath, out myLock)) 
     { 
      myLock = new ReaderWriterLockSlim(); 
      lockDict[fullPath] = myLock; 
     } 
    } 
    // only block on the file lock once the dictionary is unlocked 
    if (readOnly) 
     myLock.EnterReadLock(); 
    else 
     myLock.EnterWriteLock(); 
    // file is now "locked", so caller can proceed with read/write, then unlock 
    return myLock; 
} 

et vous pouvez l'utiliser comme ceci:

// block until we're not using the file anymore 
var myLock = LockFile(filename, readOnly: false); 
try 
{ 
    using (var file = new StreamWriter(filename)) 
    { 
    ... 
    } 
} 
finally 
{ 
    myLock.ExitWriteLock(); 
} 
+0

Un bloc 'try-finally' peut mieux fonctionner pour l'exemple d'utilisation pour s'assurer que le verrou en écriture est libéré. –

+0

@Scott: Vous ne voulez pas risquer de quitter le verrou avant que le fichier ne soit fermé, donc je ne l'ai pas implémenté avec un 'finally'. – Gabe

+0

Si l'essai englobe le bloc en cours d'utilisation, le verrou du fichier sera libéré avant le déclenchement final. 'var myLock = ...; try {using (var fichier = new StreamWriter (nom de fichier)) {...}} finally {myLock.ExitWriteLock(); } 'ou ai-je une supposition incorrecte quelque part? –

Questions connexes