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 :

Lecture d'un fichier par 2 processus : Comment éviter les erreurs d'accès concurrents ?


Sujet :

VB.NET

  1. #1
    Expert confirmé
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Points : 4 239
    Points
    4 239
    Par défaut Lecture d'un fichier par 2 processus : Comment éviter les erreurs d'accès concurrents ?
    Hello,

    Je plante le décor :

    J'ai une appli winforms qui va écrire des trucs dans un fichier texte (elle fait d'autres trucs mais sans importance pour la problématique) dans un répertoire précis. A côté de ça, il y a un service qui surveille le répertoire en question et à chaque fois qu'un fichier y est créé ou modifié, en fait une copie vers un autre serveur (situé en Allemagne).

    N.B. : Chaque utilisateur a son fichier donc pas de problème d'accès concurrent par différents utilisateurs, c'est déjà ça...

    L'opération du service est assez rapide mais de temps en temps, quand j'ai un utilisateur qui sait ce qui est un minimum organisé et, du coup, va plus vite que les autres, j'ai une erreur dans l'appli winforms à l'écriture dans le fichier car il est toujours utiliser par le service qui fait la copie.

    Du coup, hier, j'ai ajouté dans la couche métier de l'appli winforms les lignes 20 à 22 de la Sub ci-dessous et la fonction IsFileLocked :
    Code vb : 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
        Public Sub ExportToFile(ByVal sequenceNumber As Integer)
            Dim t As Date = Now
            Dim d As Date
            If t.TimeOfDay.Hours < 8 Then
                d = Today.AddDays(-1)
            Else
                d = Today
            End If
            Dim fileName As String = "TR" & d.Year.ToString.Substring(2, 2) & d.Month.ToString("00") & d.Day.ToString("00") & ".txt"
     
            Dim sw As IO.StreamWriter
     
            Dim storageFolder As String = New IO.StreamReader("BLL.conf").ReadLine
     
            If Not IO.Directory.Exists(storageFolder & "\" & Me.DTO.Store.Code & "\") Then
                IO.Directory.CreateDirectory(storageFolder & "\" & Me.DTO.Store.Code & "\")
            End If
     
            While IsFileLocked(New IO.FileInfo(storageFolder & "\" & Me.DTO.Store.Code & "\" & fileName))
                Threading.Thread.Sleep(1000)
            End While
     
            sw = New IO.StreamWriter(storageFolder & "\" & Me.DTO.Store.Code & "\" & fileName, True)
            Dim line As String
            'setting de line
            sw.WriteLine(line)
            sw.Close()
            sw.Dispose()
        End Sub
     
        Private Function IsFileLocked(file As IO.FileInfo) As Boolean
            Dim stream As IO.FileStream = Nothing
     
            Try
                stream = file.Open(IO.FileMode.Open, IO.FileAccess.ReadWrite, IO.FileShare.None)
            Catch ex As Exception
                Return True
            Finally
                If stream IsNot Nothing Then
                    stream.Close()
                End If
            End Try
            Return False
        End Function

    A priori, en cas de fichier encore utilisé, on patiente une seconde et on retente. Sauf que avec cette modif, j'ai ceci dans le journal des évènements ou l'application tourne :
    The program SEALBAG_GUI.exe version 1.0.0.0 stopped interacting with Windows and was closed. To see if more information about the problem is available, check the problem history in the Action Center control panel.
    Je n'ai malheureusement pas vu de mes propres yeux ce qui se passent mais j'imagine que doit être ce qu'il se passe quand un programme "freeze" et que windows affiche "Not responding". Par contre, pourquoi windows ferme-t-il mon appli et n'attend pas qu'elle réponde à nouveau ??
    Kropernic

  2. #2
    Expert confirmé
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Points : 4 239
    Points
    4 239
    Par défaut
    C'est encore moi.

    Il y avait quand même une erreur de logique. Si le fichier n'existe pas encore, la fonction IsFileLocked renvoie True malgré tout puisque tenter d'ouvrir un fichier qui n'existe pas génère également une exception.

    Par contre, en ayant modifiant le bloc Try pour prendre cela en compte, j'avais alors un erreur d'accès concurrent lors de l'écriture dans mon fichier. Apparemment, fermer le stream n'est pas suffisant. En le "disposant", cela résout le problème apparemment.

    J'imagine que ça doit être un truc du genre que le .Close n'est pas fait tout de suite mais quand l'OS a le temps. Tandis qu'en .Dispose, on force la fermeture immédiate.

    Par contre, sur la msdn, je peux lire ceci :
    This method calls Dispose, specifying true to release all resources. You do not have to specifically call the Close method. Instead, ensure that every Stream object is properly disposed. You can declare Stream objects within a using block (or Using block in Visual Basic) to ensure that the stream and all of its resources are disposed, or you can explicitly call the Dispose method.
    Cela veut-il dire que je peux virer le .Close et n'utiliser que .Dispose ?? Je ne sais pas d'où je tiens ça mais j'ai toujours cru que c'était le .Close qui "validait" l'écriture dans le fichier.
    N.B. : Dans ce cas-ci, vu que je n'écris rien, ce n'est pas important mais c'est bon à savoir pour plus tard.

    Voici le code de la fonction IsFileLocked avec les modifs et qui a l'air de bien fonctionner :
    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
        Private Function IsFileLocked(file As IO.FileInfo) As Boolean
            Dim stream As IO.FileStream = Nothing
     
            Try
                If file.Exists Then
                    stream = file.Open(IO.FileMode.Open, IO.FileAccess.ReadWrite, IO.FileShare.None)
                Else
                    file.Create()
                End If
            Catch ex As Exception
                Return True
            Finally
                If stream IsNot Nothing Then
                    stream.Close()
                    stream.Dispose()
                End If
            End Try
            Return False
        End Function
    Kropernic

  3. #3
    Expert confirmé
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Points : 4 239
    Points
    4 239
    Par défaut
    Bon en fait, ça marche quand je teste sur ma machine de dev mais en je viens de mettre la BLL en prod et faire tester par un user et ça ne fonctionne pas... Ca lève une exception comme quoi le fichier est déjà utilisé par un autre processus...

    Pourquoi donc ?? Mon stream est bien fermé
    Kropernic

  4. #4
    Modérateur

    Homme Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 722
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 722
    Points : 5 100
    Points
    5 100
    Par défaut
    Bonjour,

    Essaye déjà d'utiliser les "Using"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
                Using stream As IO.FileStream = Nothing
                    '...
                End Using
    Tiré de msdn : Using
    Les ressources managées sont supprimées par le garbage collector (GC) du .NET Framework sans nécessiter de codage supplémentaire de votre part. Vous n'avez pas besoin d'un bloc Using pour les ressources managées. Cependant, vous pouvez toujours utiliser un bloc Using pour forcer la suppression d'une ressource managée au lieu d'attendre le garbage collector.
    Traductions d'articles :
    La mémoire en .NET - Qu'est-ce qui va où ?
    Architecture DAL de haute performance et DTO ; Version C# : Partie 1,Partie 2,Partie 3 — Version VB.NET : Partie 1,Partie 2,Partie 3
    N'hésitez pas à consulter la FAQ VB.NET, le cours complet de Philippe Lasserre et tous les cours, articles et tutoriels.

  5. #5
    Expert confirmé
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Points : 4 239
    Points
    4 239
    Par défaut
    Si je fais cela, VS râle lors de l'affectation de stream avec file.Open car stream est apparemment en readonly...

    N.B. : J'avais d'abord voulu utiliser le bloc Using car c'est devenu une habitude. Mais vu que VS ne voulait pas, bin j'ai fait le Dispose moi-même... Mais apparemment, cela ne suffit pas...

    EDIT : Et si j'ajoute GC.Collect()... ? Mais j'ai plus de users pour tester maintenant ^^
    Kropernic

  6. #6
    Expert confirmé
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Points : 4 239
    Points
    4 239
    Par défaut C'était tellement con...
    En fait, IO.FileInfo.Create renvoie également un stream. Ce qui fait que lorsque le fichier n'existe pas, il est crée mais l'application garde "une référence" (quel est le bon terme) vers le fichier.

    En affectant le stream résultant dans ma variable stream, cette référence est bien supprimée derrière et l'accès à l'air de bien fonctionner.

    Je passe le sujet en résolu en espérant ne pas avoir à le réouvrir.

    Edit : Du coup, j'ai supprimé l'appel à GC.Collect()...
    Kropernic

  7. #7
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    Citation Envoyé par Kropernic Voir le message
    Cela veut-il dire que je peux virer le .Close et n'utiliser que .Dispose ?? Je ne sais pas d'où je tiens ça mais j'ai toujours cru que c'était le .Close qui "validait" l'écriture dans le fichier.

    il faut parfois utiliser un décompilateur pour en être sûr
    mais c'est le cas sur beaucoup de classes du framework, la méthode Dispose contient un appel à .close (cas pour les forms aussi, surement les sockets aussi ...)
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  8. #8
    Expert confirmé
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Points : 4 239
    Points
    4 239
    Par défaut
    Citation Envoyé par Pol63 Voir le message
    il faut parfois utiliser un décompilateur pour en être sûr
    mais c'est le cas sur beaucoup de classes du framework, la méthode Dispose contient un appel à .close (cas pour les forms aussi, surement les sockets aussi ...)
    Ok c'est toujours bon à savoir. Mais bon, dans le doute, un appel explicite ne fait pas de mal j'imagine... Et cela met à l'abri d'une modification ultérieure de la méthode Dispose qui retirerait pour une raison x ou y cet appel à .Close.
    Kropernic

  9. #9
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    Citation Envoyé par Kropernic Voir le message
    Ok c'est toujours bon à savoir. Mais bon, dans le doute, un appel explicite ne fait pas de mal j'imagine... Et cela met à l'abri d'une modification ultérieure de la méthode Dispose qui retirerait pour une raison x ou y cet appel à .Close.
    Un bon éditeur ne modifie pas une fonction, ca aurait de graves repercussions
    Si ms faisait ca personne n'utiliserait vs
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  10. #10
    Expert confirmé
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Points : 4 239
    Points
    4 239
    Par défaut
    Citation Envoyé par Pol63 Voir le message
    Un bon éditeur ne modifie pas une fonction, ca aurait de graves repercussions
    Si ms faisait ca personne n'utiliserait vs
    Bah lors du passage à une nouvelle version, je ne vois pas le problème. Ce serait bien sûr mentionné dans le patch note.

    Enfin soit, pour le moment, .Dispose fait appel à .Close et c'est tout ce qu'il faut retenir de cette parenthèse
    Kropernic

  11. #11
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    Citation Envoyé par Kropernic Voir le message
    Bah lors du passage à une nouvelle version, je ne vois pas le problème. Ce serait bien sûr mentionné dans le patch note.
    et pourtant
    certaines entreprises ont des gros logiciels avec du code critique, quand ils changent de version de visual studio tu crois que ca serait sérieux qu'une fonction change de fonctionnalité et qu'un programme se mette alors à planter et nécessite une réécriture complète ??
    un peu de sérieux !
    quand ms veut changer quelque chose il créé une nouvelle classe (exemple avec readerwriterlock qui ne leur plaisait plus ils ont fait readerwriterlockslim qui fait la même chose en mieux)

    un patch note de vs ou du framework c'est pas petit, ca ne mentionne pas tout, et peu de gens le lise ...
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  12. #12
    Expert confirmé
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Points : 4 239
    Points
    4 239
    Par défaut
    Bin non, personnellement, sur un changement de version, cela ne me choque pas.

    Un changement de méthode dans une version x n'affecte pas la même méthode de la version y. Donc pas de nécessité de réécriture pour l'application déjà écrite avec la méthode de la version y.

    Si on upgrade la version du framework cible, cela implique de faire des changements dans le code et c'est normal. Rien déjà que les méthodes qui sont dépréciées pour disparaître ensuite. Si j'upgrade une application du framework 2.x au 4.x, je suis quasi* certain de devoir réécrire certaines choses rien que parce que certaines méthodes ont disparues. C'est le même principe non?
    *restons prudent
    Kropernic

  13. #13
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    Citation Envoyé par Kropernic Voir le message
    Bin non, personnellement, sur un changement de version, cela ne me choque pas.

    Un changement de méthode dans une version x n'affecte pas la même méthode de la version y. Donc pas de nécessité de réécriture pour l'application déjà écrite avec la méthode de la version y.

    Si on upgrade la version du framework cible, cela implique de faire des changements dans le code et c'est normal. Rien déjà que les méthodes qui sont dépréciées pour disparaître ensuite. Si j'upgrade une application du framework 2.x au 4.x, je suis quasi* certain de devoir réécrire certaines choses rien que parce que certaines méthodes ont disparues. C'est le même principe non?
    *restons prudent
    et pourtant (une fois de plus)
    tu peux migrer une appli du fx 2 vers 4.5.1 et tout fonctionne pareil
    les choses marquées avec l'attribut "obsolète" fonctionnent toujours, ms précise juste qu'il y a mieux depuis pour faire la même chose

    après toi ca te choque pas, moi ca me choque, on ne fait peut être pas des applis de la même taille ... parce que pour moi réécrire le code en changeant de version de soft/fx ca me parait aberrant
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

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

Discussions similaires

  1. Réponses: 1
    Dernier message: 25/01/2013, 23h11
  2. lecture ecriture de fichier par blocs
    Par pfeuh dans le forum C
    Réponses: 10
    Dernier message: 06/11/2008, 10h48
  3. Synchro de l'écriture sur un fichier par plusieurs processus
    Par tnarol dans le forum Threads & Processus
    Réponses: 1
    Dernier message: 08/04/2008, 17h38
  4. Lecture d'un fichier par flots : fin de ligne ?
    Par Loïc B. dans le forum C++
    Réponses: 4
    Dernier message: 07/11/2007, 21h02
  5. Réponses: 12
    Dernier message: 13/01/2006, 10h14

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