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

C# Discussion :

"Bizarrerie" méthode Parallèle


Sujet :

C#

  1. #1
    Membre à l'essai
    Homme Profil pro
    ingénieur mécanique
    Inscrit en
    Octobre 2016
    Messages
    22
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : ingénieur mécanique

    Informations forums :
    Inscription : Octobre 2016
    Messages : 22
    Points : 18
    Points
    18
    Par défaut "Bizarrerie" méthode Parallèle
    Bonjour à tous,

    Résumé de la solution (pour couper le suspense) : Le problème si dessous, venait du fait que je tentais d'enregistrer un PDF de taille null, ce qui faisait freezer l'application.

    Voici mon problème :

    Si
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Settings.Default.B_DevMod = true
    , ça marche.
    Si
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Settings.Default.B_DevMod = false
    , la tâche ne se termine pas.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Parallel.Invoke(
        () => {
            XmlClasses.MaJPDFXml();
            if (Settings.Default.B_DevMod)
                WriteInLog.Add2log("Xml PDF à jour.");
            },
        () => {
            XAnalysePDF.GetTopIndice();
            if (Settings.Default.B_DevMod)
                WriteInLog.Add2log("Top indice définis.");
            });
    Idem, le code suivant marche :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Parallel.Invoke(
        () => {
            XmlClasses.MaJPDFXml();
            //if (Settings.Default.B_DevMod)
                WriteInLog.Add2log("Xml PDF à jour.");
            },
        () => {
            XAnalysePDF.GetTopIndice();
            //if (Settings.Default.B_DevMod)
                WriteInLog.Add2log("Top indice définis.");
            });
    Quelqu'un pourrait-il me dire pourquoi ça fait ça ?
    Est-je une solution ?

  2. #2
    Expert éminent sénior

    Avatar de François DORIN
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2016
    Messages
    2 758
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2016
    Messages : 2 758
    Points : 10 541
    Points
    10 541
    Billets dans le blog
    21
    Par défaut
    Bonjour,

    Est-ce que ton dernier code (sans les conditionnelles), fonctionne également lorsque la propriété B_DevMod est définie à false ?
    Si non, c'est que les actions exécutées en parallèle sont influencées par tes paramètres par défaut et doivent donc y faire référence, directement ou indirectement.
    François DORIN
    Consultant informatique : conception, modélisation, développement (C#/.Net et SQL Server)
    Site internet | Profils Viadéo & LinkedIn
    ---------
    Page de cours : fdorin.developpez.com
    ---------
    N'oubliez pas de consulter la FAQ C# ainsi que les cours et tutoriels

  3. #3
    Membre à l'essai
    Homme Profil pro
    ingénieur mécanique
    Inscrit en
    Octobre 2016
    Messages
    22
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : ingénieur mécanique

    Informations forums :
    Inscription : Octobre 2016
    Messages : 22
    Points : 18
    Points
    18
    Par défaut
    Bonjour,

    Oui oui, il marche avec B_DevMod à false.

    B_DevMod est un boolean qui est relié avec une checkbox (j'utilise le Settings.Default pour sauvegarder l'état à la réouverture de l'application).
    S'il est à true : j'écris un log complet.
    S'il est à false : je n'écris qu'un log partiel.
    Je ne l'utilise donc que devant WriteInLog.Add2log("...");

    Ce qui est difficile à comprendre, c'est que ça marche dans d'autres Parallel.Invoke de la même classe, du moment que la "branche" possède au moins 2 instructions :

    Marche :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    Parallel.Invoke(
        () => {
            XmlClasses.MaJPDFXml();
            if (Settings.Default.B_DevMod)
                WriteInLog.Add2log("Xml PDF à jour.");
            XAnalysePDF.GetTopIndice();
            },
        () => {
            XAnalysePDF.GetTopIndice();
            if (Settings.Default.B_DevMod)
                WriteInLog.Add2log("Top indice définis.");
            XmlClasses.MaJPDFXml();
            });
    Ne marche pas si Settings.Default.B_DevMod est à false :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Parallel.Invoke(
        () => {
            XmlClasses.MaJPDFXml();
            if (Settings.Default.B_DevMod)
                WriteInLog.Add2log("Xml PDF à jour.");
            },
        () => {
            XAnalysePDF.GetTopIndice();
            if (Settings.Default.B_DevMod)
                WriteInLog.Add2log("Top indice définis.");
            });
    J'ai l'impression que s'il y a qu'une seule instruction entre les "{}" a exécuter, sa plante...

  4. #4
    Expert éminent sénior

    Avatar de François DORIN
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2016
    Messages
    2 758
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2016
    Messages : 2 758
    Points : 10 541
    Points
    10 541
    Billets dans le blog
    21
    Par défaut
    Citation Envoyé par jaune74 Voir le message
    J'ai l'impression que s'il y a qu'une seule instruction entre les "{}" a exécuter, sa plante...
    Ce n'est pas impossible, mais reste très très peu probable. Il y a plus de probabilité que ce soit les tâches lancées qui se bloquent pour une raison ou une autre.

    En mode debug, si lorsque ton application gèle, tu la mets en pause et que tu observes les différents threads pour savoir où ils sont arrêtés, qu'obtiens-tu ?
    François DORIN
    Consultant informatique : conception, modélisation, développement (C#/.Net et SQL Server)
    Site internet | Profils Viadéo & LinkedIn
    ---------
    Page de cours : fdorin.developpez.com
    ---------
    N'oubliez pas de consulter la FAQ C# ainsi que les cours et tutoriels

  5. #5
    Membre à l'essai
    Homme Profil pro
    ingénieur mécanique
    Inscrit en
    Octobre 2016
    Messages
    22
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : ingénieur mécanique

    Informations forums :
    Inscription : Octobre 2016
    Messages : 22
    Points : 18
    Points
    18
    Par défaut
    Bonjour,

    La partie du code qui pose problème est lancé en parallèle de .

    Je lance l'application, j'attends quelques secondes, et je fais pause : le résultat est identique entre et : une seule thread "visible" qui est sur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Application.Run(new WF_MainForm());
    ...

    Pourtant, dans un cas ça marche, et dans l'autre non ... : j'ai utilisé des Sémaphores pour empêcher l'application de se fermer avant que les fonctions critiques ne soient terminées, résultat l'application ne se ferme pas...

    Je m'explique :
    Avant de lancer l'initialisation, je prend 1 jeton du sémaphore, et une fois l'initialisation terminée, je rends le jetons.
    A la fin de l'application, je compte les jetons et je ferme.

    Le jetons est pris en amont de tous ces "Paralell" et est rendu à la fin de tous cela : en aucun cas je ne manipule de jetons dans la partie incriminée.

  6. #6
    Membre à l'essai
    Homme Profil pro
    ingénieur mécanique
    Inscrit en
    Octobre 2016
    Messages
    22
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : ingénieur mécanique

    Informations forums :
    Inscription : Octobre 2016
    Messages : 22
    Points : 18
    Points
    18
    Par défaut
    Je viens d'effectuer un autre test :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    Parallel.Invoke(
        () => {
           XmlClasses.MaJPDFXml();
           if (Settings.Default.B_DevMod)
               WriteInLog.Add2log("Xml PDF à jour.");
           bool i = Settings.Default.B_DevMod;
           },
       () => {
           XAnalysePDF.GetTopIndice();
           if (Settings.Default.B_DevMod)
                WriteInLog.Add2log("Top indice définis.");
           bool i = Settings.Default.B_DevMod;
        });
    Et cela marche à tous les coup : que B_DevMod soit à true ou false ...

  7. #7
    Expert éminent sénior

    Avatar de François DORIN
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2016
    Messages
    2 758
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2016
    Messages : 2 758
    Points : 10 541
    Points
    10 541
    Billets dans le blog
    21
    Par défaut
    On a besoin de plus de code pour pouvoir comprendre le soucis. Peux-tu poster le code de la méthode dans laquelle est contenu le Parallel.ForEach ? Voir toute la classe ?

    Car d'un côté, tes tests laisse suggérer un problème d'accès concurrent. D'un autre, ils laissent penser à un bug dans Parallel.ForEach...
    François DORIN
    Consultant informatique : conception, modélisation, développement (C#/.Net et SQL Server)
    Site internet | Profils Viadéo & LinkedIn
    ---------
    Page de cours : fdorin.developpez.com
    ---------
    N'oubliez pas de consulter la FAQ C# ainsi que les cours et tutoriels

  8. #8
    Membre à l'essai
    Homme Profil pro
    ingénieur mécanique
    Inscrit en
    Octobre 2016
    Messages
    22
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : ingénieur mécanique

    Informations forums :
    Inscription : Octobre 2016
    Messages : 22
    Points : 18
    Points
    18
    Par défaut
    Je vais essayé de poster assez de code pour comprendre, et pas trop pour être claire :

    Lancement de la partie d'initialisation avec les Parallel.Foreach:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    public WF_MainForm()
    {
        if (Settings.Default.B_DevMod)
           WriteInLog.Add2log("Fin vérification existance main path."); //Ici la même portion de code marche !!
        Parallel.Invoke(
           () => InitializeComponent(),
           () => { if (!XInit.InitScheduler()) Have2Close = true; }); //Lancement de la partie contenant les Parallel.Foreach
        if (Settings.Default.B_DevMod)
            WriteInLog.Add2log("Fin de l'initialisation.");
    }
    Et la partie ou ça bug :
    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
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
     
    public static bool InitScheduler()
    {
        Semaphore _SemaErrorReport = new Semaphore(1, 1);
        string StringError = "";
        Parallel.Invoke(
            () =>
            {
                CheckDossExist(Constantes.XmlFolder, ref StringError, ref _SemaErrorReport);
                Parallel.Invoke(
                    () => CheckXmlExist(Constantes.XmlAsm, ref StringError, ref _SemaErrorReport),
                    () => CheckXmlExist(Constantes.XmlPlanPart, ref StringError, ref _SemaErrorReport));
            },
            () => CheckDossExist(Constantes.AsmFolder, ref StringError, ref _SemaErrorReport),
            () => CheckDossExist(Constantes.QuarantaineFolder, ref StringError, ref _SemaErrorReport));
        if (Settings.Default.B_DevMod)
            WriteInLog.Add2log("Folder & Xml OK"); //Marche
        if (StringError != "")
            MessageBox.Show("Les éléments suivants n'ont pas été trouvés, ils ont donc été créés :\n\n" + StringError, "Création de dossiers et de fichiers", MessageBoxButtons.OK, MessageBoxIcon.Information);
        _SemaErrorReport.Dispose();
        if (CheckNotOpen())
        {
            string s = "Un fichier de la base est ouvert (PDF ou Xml).\n";
            MessageBox.Show(s, "Le programme doit se fermer.", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            if (Settings.Default.B_DevMod)
               WriteInLog.Add2log("A File is open, app close."); //Marche
            return false;
        }
        if (Settings.Default.B_DevMod)
            WriteInLog.Add2log("Accès fichiers OK"); //Marche
        Parallel.Invoke(
            () => {
                Parallel.Invoke(
                    () => XmlClasses.OpenXmlAsm(),
                    () => XmlClasses.OpenXmlPart());
                if (Settings.Default.B_DevMod)
                    WriteInLog.Add2log("Fin de lect des Xml part & asm."); //Marche
                XERPClass.UpdateBesoin();
                if (Settings.Default.B_DevMod)
                    WriteInLog.Add2log("Fin de calcul des besoins."); //Marche
                },
            () => {
                XmlClasses.OpenXmlPDF();
                if (Settings.Default.B_DevMod)
                    WriteInLog.Add2log("Fin de lect des Xml plan."); //Ne marche pas si à B_DevMod false
                },
            () => {
                ScanDossierPlan(new DirectoryInfo(Settings.Default.Path + Constantes.PartFolder));
                if (Settings.Default.B_DevMod)
                    WriteInLog.Add2log("Fin de lecture des PDF."); //Marche
                XAnalysePDF.CompleteLectPDFS();
                if (Settings.Default.B_DevMod)
                    WriteInLog.Add2log("Fin d'analyse des noms PDF."); //Marche
                XMovePDF.RemoveDouble();
                if (Settings.Default.B_DevMod)
                    WriteInLog.Add2log("Doublons en quarantaine."); //Marche
                });
        List<string> Have2Del = new List<string>();
        using (Semaphore _SemaHave2Del = new Semaphore(1, 1))
        {
            Parallel.ForEach(Variables.Li_OldPDFSource, (PDFS) =>
                    {
                        string MotifSuppr = null;
                        if (Variables.Li_PDFSource.Exists(x => x.Ref == PDFS.Ref && x.Ind == PDFS.Ind && x.SHA1 != PDFS.SHA1))
                            MotifSuppr = "chgt sans prise d'indice.";
                        else if (!Variables.Li_PDFSource.Exists(x => x.Ref == PDFS.Ref && Convert.ToByte(x.Ind[0]) >= Convert.ToByte(PDFS.Ind[0])))
                            MotifSuppr = "suppr indice le + haut.";
                        if (MotifSuppr != null)
                        {
                            _SemaHave2Del.WaitOne();
                            if (!Have2Del.Exists(x => x == PDFS.Ref))
                                Have2Del.Add(PDFS.Ref);
                            _SemaHave2Del.Release();
                            WriteInLog.Add2log(string.Format("Tous {0} -> quarantaine : {1}", PDFS.Ref, MotifSuppr));
                        }
                    });
        }
        Parallel.ForEach(Have2Del, (suppr) =>
                {
                    XMovePDF.PDFRefToQuarantaine(suppr);
                });
        if (Settings.Default.B_DevMod)
            WriteInLog.Add2log("Fichier NOK en quarantaine.");
        Parallel.Invoke(
            () => {
                XmlClasses.MaJPDFXml();
                if (Settings.Default.B_DevMod)
                    WriteInLog.Add2log("Xml PDF à jour.");  //Ne marche pas si à B_DevMod false
            },
            () => {
                XAnalysePDF.GetTopIndice();
                if (Settings.Default.B_DevMod)
                    WriteInLog.Add2log("Top indice définis.");
                bool i = Settings.Default.B_DevMod; // Bizarrerie pour que ça marche avec B_DevMod à false.
            });
        XMovePDF.ErasePlanAsmNOK();
        if (Settings.Default.B_DevMod)
            WriteInLog.Add2log("Mise à jour des dossiers d'asm.");
        return true;
        }
    }
    Et voici ce que fait, en gros, le WriteInLog.Add2Log() :
    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
     
    public static void Add2log(string line2add)
    {
        if (line2add != null)
        {
            Variables._WriteInLog.WaitOne();
            if (Line2Write == 0)
            {
                LogPage = Log.AddPage();
                LogPage.Size = PdfSharp.PageSize.A4;
                LLine = WritePDFClass.ConvertToPDFUnit(LogPage, CellsLineWidth1_mm);
            }
            string[] ToWrite = { WritePDFClass.Dating(), line2add };
            WritePDFClass.DrawTable(LLine, ToWrite, LogPage, ref Line2Write, false);
            Variables._WriteInLog.Release();
        }
    }

  9. #9
    Membre à l'essai
    Homme Profil pro
    ingénieur mécanique
    Inscrit en
    Octobre 2016
    Messages
    22
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : ingénieur mécanique

    Informations forums :
    Inscription : Octobre 2016
    Messages : 22
    Points : 18
    Points
    18
    Par défaut
    Aussi, dans la suite de mes essais :

    Cela ne marche pas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
                    () => {
                        XmlClasses.OpenXmlPDF();
                        //if (Settings.Default.B_DevMod)
                        //    WriteInLog.Add2log("Fin de lect des Xml plan.");
                        //bool i = Settings.Default.B_DevMod; // Bizarrerie pour que ça marche avec B_DevMod à false.
                        },
    Avec le parallel.invoke, s'il n'y a qu'une seule ligne d'instruction, elle doit être écrite comme tel :
    Parallel.Invoke(()=>XmlClasses.OpenXmlPDF());
    Pas de {} ni de ; ...

  10. #10
    Membre à l'essai
    Homme Profil pro
    ingénieur mécanique
    Inscrit en
    Octobre 2016
    Messages
    22
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : ingénieur mécanique

    Informations forums :
    Inscription : Octobre 2016
    Messages : 22
    Points : 18
    Points
    18
    Par défaut
    Arpf, je crois j'ai trouvé : si je n'écrit rien dans le log, ça plante au moment de l'enregistrement du PDF ... donc rien à voir avec le Parallel.Invoke ... Je vais confirmer ça et je vous tiens au courant.

  11. #11
    Membre à l'essai
    Homme Profil pro
    ingénieur mécanique
    Inscrit en
    Octobre 2016
    Messages
    22
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : ingénieur mécanique

    Informations forums :
    Inscription : Octobre 2016
    Messages : 22
    Points : 18
    Points
    18
    Par défaut
    Bon bin je confirme, je tentais d'enregistrer un doc PDF de valeur null, d'où l'application qui tourne en rond à la fermeture ...

    Je vais essayer de supprimer le post comme le problème n'avait rien à voir avec l'intitulé.

  12. #12
    Expert éminent sénior

    Avatar de François DORIN
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2016
    Messages
    2 758
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2016
    Messages : 2 758
    Points : 10 541
    Points
    10 541
    Billets dans le blog
    21
    Par défaut
    Merci pour le retour.

    Et non, ne supprime pas le post ! Même si l'intitulé n'a rien à voir avec le problème final, initialement, tu ne le savais pas. Cela peut avoir son utilité pour d'autres
    François DORIN
    Consultant informatique : conception, modélisation, développement (C#/.Net et SQL Server)
    Site internet | Profils Viadéo & LinkedIn
    ---------
    Page de cours : fdorin.developpez.com
    ---------
    N'oubliez pas de consulter la FAQ C# ainsi que les cours et tutoriels

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

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