2009-12-10 8 views
4

Je suis en train d'écrire un fichier d'audit qui écrit le nom d'utilisateur, l'heure, et l'ancienne/modifié les valeurs de plusieurs variables dans l'application pour chaque utilisateur quand ils utilisent mon application. Il utilise un FileStream et StreamWriter pour accéder au fichier d'audit. Toutes les vérifications pour chaque utilisateur seront écrites dans le même fichier.Comment gérer les accès simultanés aux fichiers avec un flux de fichiers/flux de données?

Le problème est que lorsque deux utilisateurs mettent à jour ce fichier d'audit en même temps, l '"ancienne valeur" de chaque variable est mélangée entre les utilisateurs. Pourquoi est-ce et comment pouvez-vous résoudre le problème de concurrence ici?

Une partie du code, raccourci par souci de concision ...

Dim fs As FileStream 
Dim w As StreamWriter 

Public Sub WriteAudit(ByVal filename As String, ByVal username As String, ByVal oldAddress As String, ByVal newAddress As String, ByVal oldCity As String, ByVal newCity As String) 
    Dim now As DateTime = DateTime.Now 
    Dim audit As String = "" 
    audit += now + "," + username + "," + oldAddress + "," + newAddress + "," + oldCity + "," + newCity 

    fs = New FileStream(filename, FileMode.Append) 
    w = New StreamWriter(fs) 
    w.WriteLine(audit) 
    w.Close() 
    fs.Close() 
End Sub 

Ce vit dans une classe AuditLogger, qui est référencé par une variable d'instance (réaffectés à chaque fois que la fonction est accessible).

+0

besoin de voir le code. –

+0

J'ai ajouté un extrait de code. –

+0

Quel système d'exploitation est le serveur sur lequel cela fonctionne? (Vous pouvez peut-être utiliser un système de fichiers transactionnel.) –

Répondre

0

deux façons:

Tout d'abord, utilisez une base de données partagée et non un fichier. Même une base de données d'accès simple peut gérer plusieurs utilisateurs beaucoup plus gracieusement qu'un fichier sur le disque. Deuxièmement, pouvez-vous utiliser un fichier distinct pour chaque utilisateur? peut-être le stocker dans leur dossier% APPDATA%? Ou peut-être sur un partage réseau quelque part?

+0

Je ne peux pas faire l'un ou l'autre, malheureusement. C'est une exigence qu'aucune base de données n'est impliquée et elle est enregistrée dans un fichier .csv. Cela doit être un audit central pour chaque utilisateur à utiliser, plutôt qu'un individu pour les milliers de personnes qui l'utilisent. Cet audit est destiné à la gestion et non à l'utilisateur personnel. –

+0

Les écritures de fichiers de processus multiples sont problématiques - généralement le système d'exploitation préfère un processus unique pour régir les écritures d'écriture pour un seul handle. Un CSV est également une base de données, très simple. Pouvez-vous avoir un service partagé auquel l'application communique pour la journalisation? Cela me semble être une demande quelque peu déraisonnable de la part de la direction ou du mandat de le faire de la mauvaise façon. Juste mes deux cents. – Goyuix

2

Vous pouvez essayer ceci:

TextWriter tw = TextWriter.Synchronized(File.AppendText(filePath)); 

La méthode File.AppendText() retourne un objet StreamWriter, que la méthode TextWriter.Synchronized() enveloppe pour créer un TextWriter thread-safe qui peut être utilisé comme un StreamWriter.

+0

Cela fonctionnerait-il encore si l'instance AuditLogger était réaffectée à chaque fois comme indiqué dans la question? –

+0

Je ne sais pas, je ne l'ai pas essayé. Probablement le verrou ne le ferait pas, maintenant que j'y pense. Éditera la réponse.La documentation Synchronized Streamwriter indique seulement qu'elle rend le thread StreamWriter sûr; il ne dit rien sur la concurrence des fichiers. –

2

Refactorisez l'application afin de ne pas avoir à créer une nouvelle instance de la classe AuditLogger à chaque fois. Utilisez le singleton pattern directement, ou un cadre dependency-injection pour utiliser la même instance dans toute l'application. De là, la mise en œuvre est beaucoup plus facile: entourez les opérations d'écriture avec lock instructions, ou utilisez le TextWriter.Synchronized comme cela a été mentionné dans la réponse de Robert.

Ce poste peut être pertinent:

+0

+1 Bonne réponse. Traitez-le comme un enregistreur. Il y en a beaucoup qui fonctionnent comme ils le devraient. –

+0

Le problème qui n'est pas résolu ici est lorsque vous avez plusieurs processus essayant d'écrire dans le même fichier – Mose