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 :

Résultat trouvé différent entre Parallel.ForEach et foreach c#


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre habitué
    Homme Profil pro
    Technicien Help Desk
    Inscrit en
    Décembre 2008
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gard (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk
    Secteur : Service public

    Informations forums :
    Inscription : Décembre 2008
    Messages : 10
    Par défaut Résultat trouvé différent entre Parallel.ForEach et foreach c#
    Bonjour à tous,

    Je viens vers vous car je rencontre un problème lorsque je souhaite utiliser "Parallel.ForEach" afin de gagner du temps sur un traitement long. Le but est de faire des recherches de fichiers sur des disques durs de plusieurs GO voir Terra plus rapidement que la commande DOS "dir /b".

    Mon code ci dessous fonctionne parfaitement, le temps de traitement est de 12s pour un dossier "test" contenant 108 sous dossiers avec 421 941 fichiers. (aucune exception sur ce dossier "test")

    J'appelle la classe "Class_Recherche.cs" dans un "BackgroundWorker" qui à la fin de recherche des fichiers, compte le nombre de ligne dans mon tableau et renvoi le tableau vers un .log

    Appelle de la Class dans BackgroundWorker :
    ============================
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     DirectoryInfo dirInfo = new DirectoryInfo(textBoxBtCheminRecherche.Text);
                     string _NomRechercherLibre = textBoxOptionRecherche.Text;
     
                     List<string> _ListeFichier = new List<string>();
                     List<string> _ListeDossier = new List<string>();
     
                    Class_RechercheFichier Recherche = new Class_RechercheFichier();
                    Recherche.RechercheName(dirInfo, _NomRechercher, _ListeFichier, _ListeDossier, e, this);
     
                    UpdateLabelNbFichier(_ListeFichier.Count.ToString());
                     UpdateLabelHeureFin(UpdateHeureTraitement);
                     CreationLog.LogRechecheFichier(LettreLecteurValeur, HeureLancement, String.Join("\r\n", _ListeFichier.ToArray()), "", ActionLogRecherche, HeureFinTraitement);
                     CreationLog.LogRechecheDossier(LettreLecteurValeur, HeureLancement, string.Join("\r\n", _ListeDossier.Distinct().ToArray()), HeureFinTraitement);

    Resultat qui est correct avec Foreach :
    =========================
    Nombre de Fichier(s) trouvés: 421941



    Lorsque j'essaye d'utiliser "Parallel.ForEach" la recherche est nettement plus rapide 4s, mais le nombre de fichiers trouvés est incorrect et différent à chaque tests. Malgré x test et recherche sur Google je ne comprend pas pourquoi le nombre de fichiers est toujours inférieur au nombre réel.

    Exemple de résultat qui est incorrect avec Parallel.ForEach :
    ======================================
    Nombre de Fichier(s) trouvés: 417340
    ou
    Nombre de Fichier(s) trouvés: 420148


    Class_Recherche.cs:
    ===============
    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
     public void RechercheName(DirectoryInfo _DirInfo, string _NomRechercher, List<string> _ListeFichier, List<string> _ListeDossier, DoWorkEventArgs annulationBoucle, Form1 f1)
            {
                System.IO.FileInfo[] files = null;
                System.IO.DirectoryInfo[] subDirs = null;
     
                if (f1.ThreadRechercheName.CancellationPending)
                { annulationBoucle.Cancel = true; return; }
     
                try
                {
                    files = _DirInfo.GetFiles(_NomRechercher);
                }
                catch
                { }
     
                if (files != null)
                {
                    foreach (FileInfo file in files)
                    {
                        if (f1.ThreadRechercheName.CancellationPending)
                        { annulationBoucle.Cancel = true; break; }
                        else
                        {
                            _ListeFichier.Add(string.Join(" - ", DateTime.Now.ToLongTimeString(), file.Name));
                            _ListeDossier.Add(file.Directory.ToString());
                        }
                    }
                    subDirs = _DirInfo.GetDirectories();
                    Parallel.ForEach(subDirs, dir => RechercheName(dir, _NomRechercher, _ListeFichier, _ListeDossier, annulationBoucle, f1));
                    /*foreach (DirectoryInfo di in subDirs)
                    {
                        RechercheName(di, _NomRechercher, _ListeFichier, _ListeDossier, annulationBoucle, f1);
                    }*/
     
                }
            }

    Quelqu'un aurait-il une éventuelle réponse et solution à cette différence ?

    Merci d'avance de votre aide.

  2. #2
    Membre Expert
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Octobre 2013
    Messages
    1 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2013
    Messages : 1 563
    Par défaut
    Il peut y avoir un problème de concurrence d'accès entre les différents Threads.

    Au passage, je ne suis pas sûr que l'utilisation de la récursivité soit conseillée pour obtenir une meilleur performance.

  3. #3
    Expert confirmé

    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Septembre 2006
    Messages
    3 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Chef de projet NTIC
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Septembre 2006
    Messages : 3 580
    Par défaut
    +1 pour le

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Interlocked.Increment(ref recordCount);
    Après, si avec la récursivité, tu crées 150 thread, ça risque d'être moyen...

    d'un autre coté, si tu fais un thread par dossier, si tu as beaucoup de dossier, tu vas avoir le même soucis...

    La question pour moi serait : est-ce que la différence entre 4 et 12 secondes vaut vraiment le coup de passer des heures à faire du dev (en dehors de la curiosité
    intellectuelle)...

    Je ne connais pas les performances obtenues avec les techniques proposées ici : ICI

    et qui indique que la fonction "EnumerateFiles" te fournit tous les fichiers de façon récursive... après, est-ce optimisé, je ne saurais le dire. Pas tester avec autant de fichiers !

  4. #4
    Expert confirmé

    Homme Profil pro
    Responsable déploiement (SCCM, InTune, GPO)
    Inscrit en
    Juillet 2014
    Messages
    3 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Responsable déploiement (SCCM, InTune, GPO)
    Secteur : Transports

    Informations forums :
    Inscription : Juillet 2014
    Messages : 3 218
    Par défaut
    Plus tu lancera de thread et plus tu risquera d'allonger le temps de traitement sur un disque dur mécanique.

    Je te conseil cette class très performante
    http://www.codeproject.com/Articles/...ory-Enumerator

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