Menu

Problème avec les threads c# [Résolu/Fermé]

-
Bobjour,

Je suis bloqué depuis 2 jours sur un projet qui a pour but de vérifier l'existence d'un ou plusieurs dossiers dans une URL depuis un fichier texte.
(En gros j'ai une URL + un fichier texte avec tous les dossier à vérifier.)

Ce que j'ai fait, ça fonctionne avec un seul Thread sans soucis:
Pour lancer je fais:
           Thread thread1 = new Thread(new ThreadStart(A));
            thread1.Start();


<Foreach pour lire les lignes du fichier texte>
   foreach (string line in fichi)
                {
lien = le_site + line;
   var lixn = htcli.GetAsync(lien).Result;
                    page++;

                    add_c(list, "(" + page + "/" + page_tot + ") > " + lien, Color.Red);


                    if (lixn.StatusCode == HttpStatusCode.OK)
                    {
                        add_c(list, lien, Color.Green);
                    }
            
                }


Donc cela fonctionne avec un Thread mais si je veux par exemple que ça aille 2 fois plus vite, il faut rajouter un Thread et la le problème c'est qu'il ne m'affiche pas les résultats dans l’ordre du fichier texte.
Et pour vérifier que si déjà scanner j'aurai penser faire ça:

if(!dejascan.Contains(lien) {
//Et la le code ci-dessus
dejascan += lien;
}


Mais ça fait très brouillon et obsolète je pense.

Voila j'ai réduit le code le plus possible pour vous éviter une lecture inutile donc si il vous parais court c'est normal.

Je vous remercie d'avance pour vos réponses.
Afficher la suite 

5 réponses

Messages postés
14489
Date d'inscription
vendredi 14 mars 2003
Statut
Modérateur
Dernière intervention
25 juin 2019
165
0
Merci
Que les résultats se chevauchent c'est normal, les thread ne sont pas synchronisés.
Pour avoir une seule liste, il faudrait que tu utilise une System.Collection.Concurrent.ConcurrentQueue dans laquelle tu mette toutes tes lignes du fichier.
Ensuite, chaque thread ira piocher dans cette unique file, jusqu'à ce qu'il n'y ait plus rien dedans.

J'interviens principalement en VB6 et VB.NET, avec un peu de C#, mais la modération m'amène souvent sur d'autre langages.
En VB.NET pensez à activer "Option Explicit" et "Option Strict"
Merci pour ta réponse, Serait-il possible d'avoir un exemple ( sans forcément me mâché tout le travail )
Merci
NHenry
Messages postés
14489
Date d'inscription
vendredi 14 mars 2003
Statut
Modérateur
Dernière intervention
25 juin 2019
165 -
Je n'ai pas l'environnement sur mon ordi, mais en gros:
- Tu fais une instance (unique) de System.Collection.Concurrent.ConcurrentQueue dans laquelle tu mets toutes les lignes de ton fichier.
- Tu fais une instance System.Collection.Concurrent.ConcurrentQueue (ou ConcurrentList) pour les résultat
- Tu génères tes threads qui vont :
+ Puiser dans la collection précédemment créée
+ Faire du travail sur l'item récupéré
+ Retourner le résultat l'instance des résultats
+ Et recommencer jusqu'à ce que la file source soit vide

Les collections concurrentes (optimisées pour le threading et protégées contre les incohérences qui peuvent survenir dans ce mode) sont génériques (Classe<T>).
> NHenry
Messages postés
14489
Date d'inscription
vendredi 14 mars 2003
Statut
Modérateur
Dernière intervention
25 juin 2019
-
J'ai testé ceci:
        static string[] lines = File.ReadAllLines(@"fichier_texte.txt");
        static ConcurrentQueue<string> queue = new ConcurrentQueue<string>(lines);




 foreach (string line in fichi)
                {
     string txt = string.Empty;
                if (queue.TryDequeue(out string resultat))
                {
                    txt = resultat;
                }
lien = le_site + txt;
   var lixn = htcli.GetAsync(lien).Result;
                    page++;

                    add_c(list, "(" + page + "/" + page_tot + ") > " + lien, Color.Red);


                    if (lixn.StatusCode == HttpStatusCode.OK)
                    {
                        add_c(list, lien, Color.Green);
                    }
}
}




Je suis désolé mais j'ai jamais utilisé le System.Collection.Concurrent.ConcurrentQueue, j'ai un peu de mal, Çà fonctionne, mais si je rajoute un Thread çà m'affiche tout en double, et si j'en rajoute un troisième ca m'affichetout en triple etc .. quel serait le meilleur moyen pour régler ça? Merci d'avance
> NHenry
Messages postés
14489
Date d'inscription
vendredi 14 mars 2003
Statut
Modérateur
Dernière intervention
25 juin 2019
-
EDIT:
J'en suis arrivé la ça fonctionne, mais c'est toujours dans le désordre:
 static string[] lines = File.ReadAllLines(@"fichier_texte.txt");
        static ConcurrentQueue<string> queue = new ConcurrentQueue<string>(lines);


Et je lance mes Threads de cette manière: (2 Threads = pour aller 2 fois plus vite)
  th = new Thread(() => verif(list,lox));
            th.Start();
  th1 = new Thread(() => verif(list,lox));
            th1.Start();


 while (queue.TryDequeue(out number))
                {
  var lixn = htcli.GetAsync(solo + number).Result;
                page++;

                  add_c(list, "(" + page + "/" + page_tot + ") > " + lien, Color.Red);


                    if (lixn.StatusCode == HttpStatusCode.OK)
                    {
                        add_c(list, lien, Color.Green);
                    }
}


Je bloque vraiment la, merci d'avance !
Ok ça marche merci, je vais regardé ça de suite ! je vous tiens au courant.
Bonsoir, merci pour ta réponse, je regarde ça.
Messages postés
29
Date d'inscription
jeudi 31 mai 2018
Statut
Membre
Dernière intervention
11 juin 2018
1
0
Merci
UP + EDIT

Bonjour,

J'ai un projet qui a pour but de vérifier l'existence d'un ou plusieurs dossiers dans une URL (httpclient) depuis un fichier texte.

Pour récupérer les lignes du fichier texte j'ai fait ça:
static string[] lines = File.ReadAllLines(@"fichier_texte.txt");
 static ConcurrentQueue<string> queue = new ConcurrentQueue<string>(lines);


while (queue.TryDequeue(out number))
                {
  var lixn = htcli.GetAsync(solo + number).Result;
                page++;

                  add_c(list, "(" + page + "/" + page_tot + ") > " + lien, Color.Red);


                    if (lixn.StatusCode == HttpStatusCode.OK)
                    {
                        add_c(list, lien, Color.Green);
                    }
}


En gros il va m'afficher en rouge si le dossier n'existe pas, et en vert si il existe dans une listbox.

Mon problème c'est que j'aimerais ajouter plusieurs threads au lieu d'un seul pour que la vérification aille plus vite. Ça fonctionne, mais il ne m'affiche pas les résultats dans l'ordre.


Ex:
Fichier texte:
/dossier1
/dossier2
/dossier3

Résultats:
http://www.url.com/dossier2
http://www.url.com/dossier1
http://www.url.com/dossier3

Comment faire pour que les résultats soit dans l'ordre ?

Merci d'avance pour vos réponses.

(j'ai refait le sujet au propre ici)
Messages postés
13450
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
24 juin 2019
350
0
Merci
Est ce que tu as lu les 4 tutos que je t'ai proposés?
Il y a un passage sur le chainage des taches.
Ikikiki
Messages postés
29
Date d'inscription
jeudi 31 mai 2018
Statut
Membre
Dernière intervention
11 juin 2018
1 -
Salut, oui j'ai regardé j'ai fait plusieurs tentatives mais sans succès..
Ikikiki
Messages postés
29
Date d'inscription
jeudi 31 mai 2018
Statut
Membre
Dernière intervention
11 juin 2018
1 -
Même en reprenant le code sur le tuto pour le travailler ça ne fonctionne pas,

   public partial class Form1 : Form
    {
        static int numberOfThreads = 10;
        static int number = 1;
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Task<bool>[] tasks = new Task<bool>[numberOfThreads];
            for (int i = 0; i < numberOfThreads; ++i)
            {
                int j = i;
                checked
                {
                    tasks[i] = Task<bool>.Run(() => { return IsPrimeInRange(number, number * j / numberOfThreads, number * (j + 1) / numberOfThreads); });
                }
            }

            Task.WaitAll(tasks);
        }

        private static bool IsPrimeInRange(long number, long start, long end)
        {
            for (long i = Math.Max(start, 2); i < end; i = ++i)
            {
                if (number % i == 0L)
                {
                  MessageBox.Show("");
                }
            }

            return true;
        }

    
    }


Pourrais-tu me mettre sur une piste ?
merci
Whismeril
Messages postés
13450
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
24 juin 2019
350 -
Je n'ai jamais été confronté à ce type de besoin de synchronisation.
J'ai juste pensé que le pool de thread pouvait être une solution pour toi.
Comme tu n'avais pas dit que ça n'allait pas je t'ai demandé.
Ikikiki
Messages postés
29
Date d'inscription
jeudi 31 mai 2018
Statut
Membre
Dernière intervention
11 juin 2018
1 > Whismeril
Messages postés
13450
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
24 juin 2019
-
Ça marche merci quand même
Messages postés
13450
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
24 juin 2019
350
0
Merci
Peux tu montrer le code de la méthode add_c?
Ikikiki
Messages postés
29
Date d'inscription
jeudi 31 mai 2018
Statut
Membre
Dernière intervention
11 juin 2018
1 -
Autant pour moi,

foreach (TexteEnCouleur texte in listeTriee)
            {
                richTextBox1.AppendText(texte.Texte + Environment.NewLine);
            }


 var lixn = http.GetAsync(lien + number).Result;
                page++;
                richTextBox1.Invoke((Action)delegate
                {
                    myBag.Add(new TexteEnCouleur { Texte = "(" + page + "/" + page_tot + ") > " + lien + number, Couleur = Color.Red });
                    AfficheResultat();
                });

                if (lixn.StatusCode == HttpStatusCode.OK)
                {
                    myBag.Add(new TexteEnCouleur { Texte = "LeTexte", Couleur = Color.Green });
                    AfficheResultat();
                }




Je comprends pas c'est encore dans le désordre
Whismeril
Messages postés
13450
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
24 juin 2019
350 -
var lixn = http.GetAsync(lien + number).Result;
                page++;
                richTextBox1.Invoke((Action)delegate//ici le richtextbox on s'en fout
                {
                    myBag.Add(new TexteEnCouleur { Texte = "(" + page + "/" + page_tot + ") > " + lien + number, Couleur = Color.Red });
                    AfficheResultat();
                });

                if (lixn.StatusCode == HttpStatusCode.OK)
                {
                    myBag.Add(new TexteEnCouleur { Texte = "LeTexte", Couleur = Color.Green });//là "LeTexte" c'est devrait être remplacé par le chemin de ton dossier etc...
                    AfficheResultat();
                }


Je vais être un peu abrupte, tu nous montres un code initial digne de quelqu'un qui sait déjà bien coder.
Les threads c'est un cran au dessus, mais au départ on répond à la personne qui a écrit ce code.

Et là tu me dis que tu ne sais pas débugger
Conversion impossible de 'WindowsFormsApp10.Form1.TexteEnCouleur' en 'string'
qui est une erreur les plus basique qui soit et dont le message est quand même très clair: Tu me donnes un TexteEnCouleur alors que moi j'attends une string.

La personne qui a écrit ce code aurait suffisamment de recul sur son code pour se dire que dans l'exemple reçu sur un forum
Texte = "LeTexte"
il faut remplacer
"LeTexte"
par ce qu'on veut vraiment écrire.

Donc on est bien d'accord, tu as récupéré des bouts de codes sur le net ou ailleurs, tu les assembles un peu au petit bonheur la chance et quand ça coince, tu espères qu'un gars sur un forum, va se créer un ftp rien que pour essayer et te fournir un truc qui marche.
Déjà les forums, ça ne marche pas comme ça, on est bénévoles, on donne des pistes plus ou moins abouties, et plus ou moins exactes.
Et d'autre part, c'est pas comme ça que tu apprendras à coder, c'est en connaissant les bases de la programmation, et les bases du langages.
Je te conseille donc de laisser ton projet de coté quelques jours, de suivre un cours en ligne celui de Tahé par exemple est très bien
http://tahe.developpez.com/dotnet/csharp/

Une fois cela fait correctement, tu auras d'une part plus d'aisance à adapter les codes glaner ici et là.
Tu ne perdras plus de temps sur des erreurs simples.
Et tu auras suffisamment de recul sur ton code pour voir quelle réponse sur un forum est à adaptée et quelle autre est "clé en main" ou presque.
Ikikiki
Messages postés
29
Date d'inscription
jeudi 31 mai 2018
Statut
Membre
Dernière intervention
11 juin 2018
1 -
Oui en effet je débute, j'essaie de coder moi-même mais les Threads je ne connais pas, les ConcurrentQueue je ne connaissais pas je découvre donc oui je pioche à droite à gauche en essayant des manipulations jusqu'à que ça marche et à force ça rentre !
En ce qui concerne le
Conversion impossible de 'WindowsFormsApp10.Form1.TexteEnCouleur' en 'string'

Je n'ai pas réfléchi c'est clair j'ai posté ça prématurément..
Si je savais tout bien faire et que je connaissais le sharp parfaitement je ne serais jamais venu sur ce forum j'aurais trouvé réponse à ma question rapidement et autrement je pense.

En ce qui concerne mon projet, j'ai de la persévérance et je pense qu'il en faut ! Donc non je le mettrais pas de coté je vais continuer à me renseigner, m’instruire et finir ce projet !

Merci quand même.
Ikikiki
Messages postés
29
Date d'inscription
jeudi 31 mai 2018
Statut
Membre
Dernière intervention
11 juin 2018
1 -
Au final tout fonctionne dans l'ordre comme je voulais depuis un moment, mais avec 1 seul thread,
Si je passe à 2 ou plus c'est là que j'ai les résultats dans le désordre nous allions peut-être sur une fausse piste...
Enfin bref, Tan pis merci CCM !
Whismeril
Messages postés
13450
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
24 juin 2019
350 -
Non tu ne m'as pas bien lu, ou je n'ai pas été clair, je ne te dit pas d'arrêter ton projet, mais de le mettre en pause quelques jours, le temps d'apprendre les bases, bases que tu n'as manifestement pas.
On ne peut pas faire de multiplication correcte (et c'est pas dur) avant d'avoir bien intégrer l'addition.
Là c'est pareil.

en essayant des manipulations jusqu'à que ça marche et à force ça rentre
ça c'est la mauvaise méthode, je l'ai fait aussi, bien avant toi, ça finit toujours par coincer, parce qu'on fait les "manipulations" sans connaitre et comprendre les tenants et les aboutissants.

Si tu as, comme tu le dis, de la persévérance, le cours de Tahé va te prendre, 4 ou 5 jours, qu'est-ce que c'est pour savoir mieux apprendre à coder le reste de ta vie?