2016-09-09 1 views
0

Bonjour et merci pour votre aide. Cette fois, j'ai un problème curieux avec un programme (C#) que j'écris et j'aimerais avoir votre avis. J'écris un programme normal (pas multithread) mais ai ensuite ajouté un temporisateur (System.Timers.Timer)Minuteurs, fichiers et conditions de course?

Aussi j'utilise un StreamWriter pour écrire sur un dossier. J'ouvre ce comme ça

StreamWriter logStream=new StreamWriter(filename, true); 

ce qui signifie que si le fichier existe, il ajoute, sinon il crée.

Plus tard, j'écrire dans le fichier comme celui-ci

logStream.WriteLine(message); 

Cependant, j'écris au courant de deux la fonction principale et de la fonction qui est appelée par la minuterie.

les symptômes du problème

Mon programme est de lancer une erreur parfois quand je tire la chasse ou écrire le flux en disant que « Impossible d'accéder à un fichier fermé » et d'autres fois « ne peuvent pas accéder à un TextWriter fermé ... (Qu'est-ce qu'un « TextWriter »?)

Cependant curieusement, le fichier continue à être écrit sans problème. (Même le « ne peut pas accéder à un fichier fermé » message est écrit dans le fichier fermé supposé)

Je suis pas familier avec le fonctionnement interne d'une minuterie. (Je suppose qu'il fonctionne un sep fil arate?)

Ma question est

Est-il possible d'utiliser un StreamWriter de plusieurs threads? (dans ce cas le principal et le minuteur) Est-il possible qu'il se passe une condition de course ou un problème comme celui-là?


Encore une chose: je fait une erreur logique et fermez et rouvrez le fichier chaque fois que je veux écrire sur elle. Oui, c'est une erreur et je devrais le corriger. Mais peut-être que si je corrige cela, l'erreur que j'ai décrite ci-dessus disparaîtra en masquant un défaut plus sérieux.

Mes soupçons est que depuis que je suis fermeture et l'ouverture du fichier chaque fois j'écris dessus, peut-être les fils les deux tentent d'y accéder à un mauvais moment

Toute aide sera grandement appréciée

+0

À l'une de vos questions: Un StreamWriter est un TextWriter spécifique. –

+2

Essayez-vous de créer une implémentation de journalisation? Pourquoi n'utilisez-vous pas.L'API de diagnostic intégrée de NET ou une bibliothèque de journalisation comme log4net? Les bibliothèques de consignation doivent accepter les demandes de consignation provenant de plusieurs threads mais écrire correctement toutes les entrées sans corrompre le fichier journal. –

Répondre

1

La fermeture et l'ouverture de votre fichier dans ce scénario créeront une condition de concurrence comme vous le suspectez. Vous ne pouvez pas garder le flux ouvert et passer l'objet au thread car vous pourriez vous retrouver avec un problème similaire si vous appelez depuis un thread différent. Votre meilleure solution reste d'utiliser une méthode thread-safe qui écrira ce que vous lui envoyez.

les méthodes sont statiques car le verrou doit être accessible à partir de toutes les instances de la classe.

private static ReaderWriterLockSlim readerWriterLockSlim = new ReaderWriterLockSlim(); 

public static void AppendToFile(string path, string text) 
{ 
    // Set to locked (other thread will freeze here until object is unlocked 
    readerWriterLockSlim.EnterWriteLock(); 

    try 
    { 
     // Write that will append to the file 
     using (StreamWriter sw = File.AppendText(path)) 
     { 
      // append the text 
      sw.WriteLine(text); 
      sw.Close(); 
     } 
    } 
    finally 
    { 
     // Clear the lock 
     readerWriterLockSlim.ExitWriteLock(); 
    } 
} 
+1

Mieux encore, utilisez une bibliothèque de journalisation. Ou un ActionBlock qui met en file d'attente des messages provenant de plusieurs threads et les écrit un par un en utilisant un simple rédacteur –