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

Framework .NET Discussion :

[C#][2.0] Sauvegarde d'un DataSet dans des threads différents


Sujet :

Framework .NET

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Inscrit en
    Août 2006
    Messages
    381
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 381
    Par défaut [C#][2.0] Sauvegarde d'un DataSet dans des threads différents
    Bonjour,

    je suis confronté à un problème assez délicat:
    La sauvegarde d'un DataSet dans des threads différents.

    Ce code est exécuté sur un serveur. Le client identifie le bidon à l'entrée du convoyeur et appelle la méthode EntreeBidon.
    Le bidon est ajouté à une file d'attente puis le statut est sauvegardé dans la base de données via .Net Remoting car cette base de données est géré par un serveur distant lui aussi.

    Lorsque le bidon sort du convoyeur la méthode SortieBidon est appelé.
    J'ai quelques soucis comme je le disais pour la gestion des threads. En effet, la sauvegarde dans la base de données est susceptibles de prendre un peu de temps. J'utilise donc le pool de threads pour la sauvegarde.
    Pour ne pas avoir de problème d'accès concurrents, j'ai utilisé un lock pour verrouiller le DataSet à sauvegarder, mais je ne trouve pas ça terrible.

    Comment devrais-je faire selon vous ?

    Voilà comment j'ai procédé

    Code c# : 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
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
     
    private Queue<ProduitDataSet.BidonRow> m_FileBidons;
     
    void EntreeBidon(ProduitDataSet dsProduits, int idBidon)
    {
          ProduitDataSet.BidonRow bidon = dsProduits.Bidons.FindByBidonId(idBidon);
     
          if (bidon!=null)
          {           
               m_FileBidons.Enqueue(bidon);
     
    	   bidon.Statut = "EnCours";
     
               // Sauvegarde du DataSet des produits
               ThreadPool.QueueUserWorkItem(new WaitCallback(SaveProduitDataSet), dsProduits);
     
          }
    }
     
     
            /// <summary>
            /// Sauvegarde du DataSet
            /// </summary>
            private void SaveProduitDataSet(object objProduitDataSet)
            {
                ProduitDataSet dsProduit = objProduitDataSet as ProduitDataSet;
     
                lock (m_ProduitDataSet)
                {
                    // Fusion des bidons modifiés
                    if (dsProduit.Bidons.GetChanges(DataRowState.Modified) != null)
                    {
                        m_ProduitDataSet.Bidons.Merge(dsProduit.Bidons.GetChanges(DataRowState.Modified), false);
                    }
     
                    // Sauvegarde du DataSet
                    try
                    {
                        // Test Endormissement du thread courant
                        Console.WriteLine("Endormissement du Thread. {0}", Thread.CurrentThread.ManagedThreadId);
                        System.Threading.Thread.Sleep(10000);
                        Console.WriteLine("Réveil du Thread. {0}", Thread.CurrentThread.ManagedThreadId);
     
     
                        // Sauvegarde du DataSet
                        // m_GestionProduit est une interface distante accessible via .Net Remoting
                        m_GestionProduit.SaveProduits(m_ProduitDataSet);
     
     
                        // Valide les changements apportés
                        m_ProduitDataSet.AcceptChanges();
     
                    }
     
                    catch (Exception ex)
                    {
                        log.Error("Erreur lors de la sauvegarde du DataSet des produits.", ex);
                    }
                }
            }
     
     
            private void SortieBidon()
            {
                 ProduitDataSet.BidonRow bidon = dsProduits.Bidons.FindByBidonId(idBidon);
     
                 bidon.Statut = "Termine";
     
                 SaveBidon(bidon);    
     
            }
     
            /// <summary>
            /// Sauvegarde des modifications apportées à la ligne d'un bidon
            /// </summary>
            private void SaveBidon(ProduitDataSet.BidonRow rowBidon)
            {
                if (rowBidon!= null)
                {
                    // Transtypage de la table du carton
                    ProduitDataSet.BidonsDataTable dtBidons = rowBidon.Table as ProduitDataSet.BidonsDataTable;
     
                    try
                    {
                        // Sauvegarde des modifications du cartons
                        m_GestionProduit.SaveBidon(dtCartons, rowBidon.BidonId);
     
                        rowBidon.AcceptChanges();
                    }
                    catch (Exception ex)
                    {
                        log.Error("Erreur lors de la sauvegarde du bidon.", ex);
                    }
                }
            }

    Je suis désolé si ce message est un peu long mais j'y suis obligé.
    En espérant avoir été clair.

    Merci d'avance pour votre aide.
    A bientôt

  2. #2
    Membre Expert Avatar de Mose
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 143
    Détails du profil
    Informations personnelles :
    Âge : 48
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 143
    Par défaut
    Suggestion :
    * tu encapsules ton DataSet dans un objet métier.
    * tu y colles un booleén 'busy' que tu mets à vrai quand tu lance ta sauvegarde
    * si qqn essayes d'accéder au DataSet (via les méthodes de ton objet métier), tu vérifies qu'il n'est pas "busy". S'il l'est, tu vois ce que tu fais (annuler la sauvegarde, ou faire patienter la modification)

    Maintenant, faut voir si ça colle avec ton archi...

  3. #3
    Membre éclairé
    Inscrit en
    Août 2006
    Messages
    381
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 381
    Par défaut
    Bonsoir,

    pas bête l'idée du busy. Je vais voir.
    Et tu as eu le temps de jeter un coup d'oeil à mon code ? Qu'en penses-tu ? Oui oui je sais y en a des tartines. Tu confirmes que les lock, ce n'est pas terrible ?

    Merci d'avance.
    Bye

  4. #4
    Membre Expert Avatar de Mose
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 143
    Détails du profil
    Informations personnelles :
    Âge : 48
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 143
    Par défaut
    Bein... les lock avec le gros sleep(10000) dedans, effectivement je trouve pas ça terrible

    Perso j'évite les lock le plus possible, généralement, l'utilisation d'un booléan permet d'éviter bien des soucis à un coût très minime en perfs.

    Une autre solution : tu fais un lock, tu clones ton DataSet, tu sors du lock et tu fait ta sauvegarde avec le clone, comme ça l'autre peut être modifié sans impacts.

  5. #5
    Membre éclairé
    Inscrit en
    Août 2006
    Messages
    381
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 381
    Par défaut
    Bonsoir,

    Bein... les lock avec le gros sleep(10000) dedans, effectivement je trouve pas ça terrible
    Oui tu m'étonnes. J'ai utilisé un sleep pour simuler le blocage de l'appli. Evidemment en prod, ce sleep n'y ait pas.

    Mon archi est la suivante:
    Une application serveur de gestion gérant les accès à la base de données.
    Une application serveur de suivi de produit.
    Le serveur de suivi de produit est client du serveur de Gestion (.Net Remoting).
    Au total, le serveur de gestion a 8 clients et le serveur de traitement a 4 clients.

    Si je mets un booleen busy comme tu me l'as suggéré, les sauvegardes du DataSet ne seront pas possible tant que ce booleen n'est pas à false.
    Le serveur de traitement sauvegarde très régulièrement en base le DataSet.
    Il risque donc d'occuper très souvent l'opération de sauvegarde du DataSet sur le serveur de Gestion et les autres clients ne pourront pas sauvegarder comme ils le souhaitent. Non ? Qu'en penses-tu ?

    L'autre solution n'est pas mal non plus.

    Je te remercie pour tes conseils.
    Bye

  6. #6
    Membre éclairé
    Inscrit en
    Août 2006
    Messages
    381
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 381
    Par défaut
    Bonjour,

    je galère toujours avec ce problème.
    En fait, j'ai un contrôle utilisateur et une classe métier.
    L'utilisateur scan un code-barre avec une douchette. Celui-ci est transmis sous forme de chaîne de caractère à la classe métier.
    Celle-ci effectue un traitement et sauvegarde les données dans un DataSet qui est ensuite sauvegardé dans la base de données à chaque scan.
    Je devrais peut-être faire de ma classe métier une classe thread-safe ?
    Non ? Qu'en pensez-vous ?
    Si j'utilise un booleen, il faut que je m'assure aussi qu'il n'est pas modifié par plusieurs thread différent.

    Merci pour votre aide.

Discussions similaires

  1. Réponses: 3
    Dernier message: 12/04/2011, 15h16
  2. Réponses: 2
    Dernier message: 30/08/2007, 08h28
  3. Réponses: 1
    Dernier message: 27/06/2006, 13h09
  4. [VB.NET] Création MDIChild dans un thread différent
    Par XnoTonio dans le forum Windows Forms
    Réponses: 5
    Dernier message: 19/05/2006, 15h53
  5. Comparaison de 2 dates dans des formats différents
    Par frdek dans le forum Langage SQL
    Réponses: 2
    Dernier message: 14/02/2005, 15h05

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