IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

VB.NET Discussion :

Classe de Log avec pattern Singleton


Sujet :

VB.NET

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Août 2005
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Août 2005
    Messages : 21
    Par défaut Classe de Log avec pattern Singleton
    Bonjour,

    Je désire me faire une classe de Logging thread-safe. Malgré plusieurs essais, il arrive toujours un moment ou j'obtiens des exceptions :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    The process cannot access the file 'Application.log' because it is being used by another process.
    Pourriez-vous m'aider à trouver ce que je fais de mal ?
    Voici ma classe :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    Imports System.IO
    Imports System.Threading
     
    Public Class Logging
     
        ' Signleton 
        Private Shared instance As Logging = Nothing
        Private Shared ReadOnly myLock As New Object()
        Private m_lock As New System.Threading.ReaderWriterLock
     
        Private Sub New()
     
        End Sub
     
     
        Public Shared Function GetInstance() As Logging
            SyncLock (myLock)
                If instance Is Nothing Then
                    instance = New Logging()
                End If
     
                Return instance
            End SyncLock
        End Function
     
        ' End Signleton
     
        Private m_fileName As String
     
        Public Property FileName As String
            Get
                Return m_fileName
            End Get
            Set(ByVal value As String)
                m_fileName = value
            End Set
        End Property
     
     
        Private m_sw As StreamWriter = Nothing
        Private m_currDate As Date = DateTime.Now()
     
     
        Public Sub Add(ByVal str As String)
            Try
                m_lock.AcquireWriterLock(100)
                Try
                    If DateTime.Now().Day <> m_currDate.Day Then
                        Dim newfile As New FileInfo(m_fileName)
                        If newfile.Exists Then
                            m_sw = New StreamWriter(m_fileName, True)
                            m_sw.WriteLine(DateTime.Now.ToString("HH:mm:ss") + " - Day is over, renaming file and creating new one ...")
                            m_sw.Close()
                            m_sw = Nothing
                            newfile.MoveTo(m_fileName + "." + m_currDate.ToString("ddMMyyyy") + ".log")
                            m_currDate = DateTime.Now()
                        End If
                    End If
                    m_sw = New StreamWriter(m_fileName, True)
                    m_sw.WriteLine(DateTime.Now.ToString("HH:mm:ss") + " - " + str)
                    m_sw.Close()
                    m_sw = Nothing
                Finally
                    m_lock.ReleaseWriterLock()
                End Try
            Catch ex As ApplicationException
            Catch e As IOException
                EventLog.WriteEntry("MyServer", "Could not operate log file actions : " + e.Message)
                'm_sw = New StreamWriter(m_fileName, True)
                'm_sw.WriteLine(DateTime.Now.ToString("HH:mm:ss") + " - Error in adding line to log file " + e.Message)
                'm_sw.Close()
                'm_sw = Nothing
            End Try
        End Sub
     
     
    End Class
    J'appelle ma classe de Logging de la façon suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Logging.GetInstance().Add("ChangeChannel has been called for " + Sender + " on channel " + Channel)
    Je précise, au début j'avais créé ma classe sans objet ReaderWriterLock, je l'ai rajouté entre-temps suite à mes recherches sur internet, mais malgré cela je continue à avoir des exceptions.

    Un idée ?

    D'avance je vous en remercie,

    Dominique

  2. #2
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    1 048
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2009
    Messages : 1 048
    Par défaut
    Hello

    Pourquoi tu n'utiliserais pas plutot une collection thread-safe (comme ConcurrentStack ou ConcurrentQueue) pour charger les logs et un thread spécifique qui s'occupent de vider cette liste en écrivant le log dans ta base de donnée (ou un fichier) ?

    http://msdn.microsoft.com/en-us/library/dd997305.aspx

    Ton SyncLock ne protège que la méthode renvoyant l'instance du singleton, pas la suite (La fonction .Add de ce dernier)

    Au lieu de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Logging.GetInstance().Add("ChangeChannel has been called for " + Sender + " on channel " + Channel)
    Tu enlève le SyncLock dans le GetInstance, tu modifies la portée du MyLock (en public) puis :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    SyncLock (Logging.MyLock)
    Logging.GetInstance("ChangeChannel has been called for " + Sender + " on channel " + Channel).Add
    End SyncLock
    http://msdn.microsoft.com/fr-fr/libr...(v=vs.80).aspx

    A noter que la solution proposée en contournement à l'avantage de ne pas stopper ton code au log si un autre thread est déjà en train d'enregistrer un log.

    Si tu imagines qu'inscrire ton log c'est classer une feuille dans un classeur.

    La solution SyncLock équivaux à mettre en place une règle indiquant que seul une personne peut avoir le classeur (ça semble con mais en prog faut l'implémenter...). Si un de tes collègues à le classeur, tu dois attendre qu'il a fini son affaire.

    La solution de liste thread safe avec un thread dédié à l'écriture de ces derniers c'est comme l'embauche d'une secrétaire. Les gens posent la feuille en vrac dans son bac d'entrée, elle s'occupe de vider le bacs et de les mettres dans le classeur à son rytme. Bon tu grilles une partie de ton budget (ressource CPU) en embauchant la secrétaire.

    Chaque solution a ses avantages et inconvéniants selon l'environnement. A toi d'étudier la chose.

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Août 2005
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Août 2005
    Messages : 21
    Par défaut
    Bonsoir Sinople,

    Je vais regarder les collections thread-safe, ca ne devrait poser aucun problème de ressource dans le cadre de projet. Je vais surement partir vers cette solution, mais par contre, et ce pour ma curiosité personnel, il me semblait que :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    m_lock.AcquireWriterLock(100)
                Try
                ...
                Finally
                    m_lock.ReleaseWriterLock()
                End Try
    Le AcquireWriterLock et ReleaseWriterLock devrait agir un comme le SyncLock extérieur que tu proposes non ?

    Encore merci de ton aide,

    Dominique

  4. #4
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    1 048
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2009
    Messages : 1 048
    Par défaut
    Hello,

    Je suis pas un grand spécialiste de la programmation parallèle et des threads mais d'après ce que j'ai pu lire dans la doc MSDN.

    http://msdn.microsoft.com/en-us/libr...riterlock.aspx

    Ton AcquireWriterLock fait un peu double office avec ton SyncLock, ça peut être source d'embrouille...

    Plus globablement le ReadWriterLock est utile s'il y a beaucoup de thread qui désire lire les infos et peu qui veulent écrire. Pour reprendre l'exemple précédant, il laisse soit une personne mettre une feuille dans ton classeur soit une infinité de personne le consulter en même temps.

    Contrairement au SyncLock qui lui ne laisse l'accès que à un thread (que ça soit pour la lecture ou l'écriture). Malheureusement dans ton cas c'est plutôt l'inverse, c'est beaucoup de monde qui veut ecrire, il y a donc pas de gain!

    Les exceptions peuvent provenir du timeout de 100ms, c'est à dire que si l'écriture de ton log dure plus de 100 ms il balance une exception et passe le lock au prochain. L'ouverture d'un fichier, ça peut vite être un peu long (c'est surtout une valeur très volatile ce qui risque de poser des problèmes à chaque fois que la machine doit bosser beaucoup...)

    Tu as essayer de modifier ton sync lock comme je l'ai proposé précédement (Keep-it simple...).

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Août 2005
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Août 2005
    Messages : 21
    Par défaut
    Bonsoir,

    Cela fait depuis ce matin que ca tourne avec le SyncLock externe, pour l'instant ca me convient. Je verrai pour implémenter les collections Thread-Safe plus tard.

    Un grand merci de ton aide, je marque résolu le post.

    Dominique

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Générer des classes Java à partir de xsd avec patterns
    Par Danicela dans le forum Format d'échange (XML, JSON...)
    Réponses: 0
    Dernier message: 30/10/2012, 17h58
  2. Réponses: 0
    Dernier message: 12/04/2012, 18h35
  3. [Singleton] Classe static ou Design Pattern Singleton ?
    Par piloupy dans le forum Design Patterns
    Réponses: 15
    Dernier message: 01/08/2008, 16h04
  4. Réponses: 3
    Dernier message: 15/04/2008, 14h40
  5. Pattern singleton ou Classe avec méthodes statiques ?
    Par Claythest dans le forum Langage
    Réponses: 3
    Dernier message: 11/12/2006, 11h28

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo