Threads en csharp

Résolu
moi411 Messages postés 179 Date d'inscription samedi 22 novembre 2003 Statut Membre Dernière intervention 25 juin 2017 - 9 juil. 2007 à 02:24
TeBeCo Messages postés 467 Date d'inscription lundi 24 juin 2002 Statut Membre Dernière intervention 9 mars 2011 - 10 juil. 2007 à 18:52
Bonsoir à tous,
Pour être bref le thread que j'utilise marche mais seulement avec l'utilisation d'une MessageBox dans le programme principal...
Mon programe sert à rechercher des fichiers sur le dique dur et à afficher le chemin complet du dossier qui en cour d'examen dans une textbox (d'ou besoin d'un thread, si j'ai bien compris!).
J'ai voulu faire comme le programme de recherche dans windows, pour donner une vague idée du résultat...
Pour la recherche ,donc, j'utilise une fonction récursive, avec une boucle qui "garde le contrôle" sur le reste du programme et donc du thread (lui même déclaré et démarré avant cette boucle). Je mets une MessageBox qui est "utilisée" à chaque itération dans ma boucle et là tout fonctionne comme il faut mais j'ai envie d'enlever cette MessageBox. C'est à ce moment là que ça ne fonctionne plus...
Voilà j'espère que je me suis exprimé correctement et que quelqu'un pourra me m'aider!
Merci d'avance (éventuellement bonne nuit) et ci-joint le code commenté:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Threading;

namespace WindowsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        //déclaré ici car besoin dans AfficherChemin() (voir Thread)
        string nomFichier;
       

        private void button1_Click(object sender, EventArgs e)
        {
            //rep ou commencer la recherche
            DirectoryInfo rep = new DirectoryInfo(@"C:");

            //Thread servant à afficher les fichier trouvé par Chercher(rep);
            Thread t = new Thread(new ThreadStart(AfficherChemin));
            t.Name = "TChemin";
            t.Start();

            //fonction de recherche (récurcive)
            Chercher(rep);
        }
       

        public void Chercher(DirectoryInfo Rep)
        {
            try
            {
                //récupère le chemin complet du fichier
                nomFichier = Rep.FullName;

                //dans le répertoire courant on cherche tous les fichiers
                //dont l'extension est .txt
                foreach (FileInfo f in Rep.GetFiles("*.txt"))
                {

                    //Comment faire sans message box???
                    MessageBox.Show("");

                    //et on on crée un item avec les chemeins et tailles de ces fichiers
                    //item qui sera ajouté à la listview
                    ListViewItem it = new ListViewItem();
                    it.Text = f.FullName;
                    it.SubItems.Add(f.Length.ToString());
                    listView1.Items.Add(it);
                }
            }
            catch { }
           
            try
            {
                //si il y a des sous répertoires on rappelle "Chercher();" (principe de la récursivité)
                DirectoryInfo[] a = Rep.GetDirectories();
                foreach (DirectoryInfo b in a)
                {
                    Chercher(b);
                }
            }
            catch { }

        }
       

        //le thread appelle cette fonction qui affiche
        //dans une textBox, tous les chemins
        //des fichier texte sur un disque (C:).
        public void AfficherChemin()
        {
            while (true)
            {
                textBox1.Text = nomFichier;            
                Thread.Sleep(0);
            }
        }
    }
}

10 réponses

moi411 Messages postés 179 Date d'inscription samedi 22 novembre 2003 Statut Membre Dernière intervention 25 juin 2017 3
9 juil. 2007 à 17:46
           Re,
Ca y est je crois que j'ai compris... d'ailleurs ça marche maintenant comme je le veux, mais je ne sais pas si je peux faire comme ça. En fait j'aimerais savoir si il n'y a pas une façon plus "officielle" de le faire?
Et puis si je puis me permettre une autre question, la délégation (dans ce cas-ci) sert à "expliquer" à l'ordinateur qu'on doit afficher dans la textbox à partir d'un thread (thread secondaire) autre que celui qu'il a utilisé (thread principal) pour créer ladite textbox.
Est-ce que j'ai bien compris?

Dans tous les cas je te remercie de m'avoir mis sur la voie.
A bientôt.

Eventuellement le code fonctionnel:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Threading;

namespace WindowsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
             
       
        //délégation servant à afficher dans la textbox
        delegate void AjoutTextBoxText(string Texte);
        public void AjoutTextBox(string Texte)
        {
            textBox1.Text = Texte;
        }

        //Même chose avec la listview
        delegate void AjoutListViewItem(string chem, string taille);
        public void AjoutListView(string chem, string taille)
        {           
            ListViewItem it = new ListViewItem();
            it.Text = chem;
            it.SubItems.Add(taille);
            listView1.Items.Add(it);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //rep ou commencer la recherche
            DirectoryInfo rep = new DirectoryInfo(@"C:");

            //Thread servant commencer la recherche
            Thread t = new Thread(new ThreadStart(AfficherChemin));
            t.Name = "TChemin";
            t.Start();
        }

        public void Chercher(DirectoryInfo Rep)
        {
            try
            {
                //récupère le chemin complet du dossier où se trouve le fichier
                AjoutTextBoxText ajoutText = new AjoutTextBoxText(AjoutTextBox);
                Invoke(ajoutText, new object[] { Rep.FullName });

                //récupère le nom du fichier ainsi que sa taille
                AjoutListViewItem ajoutItem = new AjoutListViewItem(AjoutListView);
               
                //dans le répertoire courant on cherche tous les fichiers
                //dont l'extension est .txt
                foreach (FileInfo f in Rep.GetFiles("*.txt"))
                {
                    Invoke(ajoutItem, new object[] { f.FullName, f.Length.ToString() });                   
                }
            }
            catch { }

            try
            {
                //si il y a des sous répertoires on rappelle "Chercher();" (principe de la récursivité)
                DirectoryInfo[] a = Rep.GetDirectories();
                foreach (DirectoryInfo b in a)
                {
                    Chercher(b);
                }
            }
            catch { }

        }

        //le thread appelle cette fonction qui les fichier texte sur un disque (C:).
        public void AfficherChemin()
        {
            DirectoryInfo rep = new DirectoryInfo(@"C:");
            Chercher(rep);           
        }
    }
3
TeBeCo Messages postés 467 Date d'inscription lundi 24 juin 2002 Statut Membre Dernière intervention 9 mars 2011
9 juil. 2007 à 18:27
et la je me dit qu'il faut surment aussi rajouté un "textbox.refresh()" (ou .Update() je confond tjs les 2 cf la doc) ^^
ca parraissait tellement naturel que je l'ai zappé

TeBeCo
3
TeBeCo Messages postés 467 Date d'inscription lundi 24 juin 2002 Statut Membre Dernière intervention 9 mars 2011
9 juil. 2007 à 08:36
je ne sais pas si ca resoudra le pb cependant je t'invite a modifié un poil certain point de ton code par exemple :

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Threading;

namespace WindowsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        //déclaré ici car besoin dans AfficherChemin() (voir Thread)
        string nomFichier;
        Thread t;
        delegate void SetTextBoxTextHandler(String texte);
        SetTexteBoxTextHandler dlgTxt;

        private void button1_Click(object sender, EventArgs e)
        {
            //rep ou commencer la recherche
            DirectoryInfo rep = new DirectoryInfo(@"C:");

            //Thread servant à afficher les fichier trouvé par Chercher(rep);
            t = new Thread(new ThreadStart(AfficherChemin));
            t.Name = "TChemin";
            t.IsBackground = true; // thread de background pour le CPU
            t.Priority = ??? // A toi de voir
            <strike>t.Start();</strike>

             dlgTxt = new SetTexteBoxTextHandler(SetTextBoxText)
              //j'ai un trou de mémoire sur la methode dont on rattache un delegué a une methode mais il faut le rattaché a
            "SetTextBoxText" a corriger si la ligne du dessus est fausse

            //fonction de recherche (récurcive)
            Chercher(rep);
        }

       private void SetTextBoxText(String texte)
       {
             this.textbox1.text = texte;
       }
       

        public void Chercher(DirectoryInfo Rep)
        {
            try
            {
                //récupère le chemin complet du fichier
                nomFichier = Rep.FullName;
                t.Start();

                //dans le répertoire courant on cherche tous les fichiers
                //dont l'extension est .txt
                foreach (FileInfo f in Rep.GetFiles("*.txt"))
                {

                    //Comment faire sans message box???
                    MessageBox.Show("");

                    //et on on crée un item avec les chemeins et tailles de ces fichiers
                    //item qui sera ajouté à la listview
                    ListViewItem it = new ListViewItem();
                    it.Text = f.FullName;
                    it.SubItems.Add(f.Length.ToString());
                    listView1.Items.Add(it);
                }
            }
            catch { }
           
            try
            {
                //si il y a des sous répertoires on rappelle "Chercher();" (principe de la récursivité)
                DirectoryInfo[] a = Rep.GetDirectories();
                foreach (DirectoryInfo b in a)
                {
                    Chercher(b);
                }
            }
            catch { }

        }
       

        //le thread appelle cette fonction qui affiche
        //dans une textBox, tous les chemins
        //des fichier texte sur un disque (C:).
        public void AfficherChemin()
        {
            while (true)
            {
                <strike>textBox1.Text = nomFichier;</strike>
                This.Invoke(dlgTxt, new Object(){nomFichier}); // j'emet un doute sur la syntaxe je susi pas bien reveillé
                Thread.Sleep(10/* ou autre mais 0 c'est vraiment à voir */ );
                Application.DoEvents();
            }
        }
    }
}

TeBeCo
0
TeBeCo Messages postés 467 Date d'inscription lundi 24 juin 2002 Statut Membre Dernière intervention 9 mars 2011
9 juil. 2007 à 08:37
ps :  j'ai pas du tout regarder le fonction de la boucle recursive je vais taffer a plus surment

TeBeCo
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
moi411 Messages postés 179 Date d'inscription samedi 22 novembre 2003 Statut Membre Dernière intervention 25 juin 2017 3
9 juil. 2007 à 15:37
            Re,
J'ai fait toutes les modifications, la délégation et l'invocation ont l'air de fonctionner correctement (pour preuve les MessageBox) mais ma textBox ne récupère toujours pas mes chemins de fichiers. Je me suis renseigné sur l'utilité de la délégation et de l'invocation et maintenant je comprends pourquoi ont doit les utiliser. Mais je n'arrive toujours pas à comprendre comment le faire!!!
Sinon j'ai réessayer d'enlever la messageBox de ma fonction récursive et le résultat est toujours le même...

Je te/vous remercie d'avance dans le cas où tu/vous m'aiderais à nouveau...
A bientôt.

Ci-joint le code comenté:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Threading;

namespace WindowsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        //déclaré ici car besoin dans AfficherChemin() (voir Thread)
        public delegate string SetTextBoxTextHandler(string Texte);
        string nomFichier;
        Thread t;
        SetTextBoxTextHandler dglTxt;

        //méthode qui sera enregistré dans l'objet délégué
        public static string RecupText(string Texte)
        {           
            return Texte;
        }
         
             
        private void button1_Click(object sender, EventArgs e)
        {           
            //rep ou commencer la recherche
            DirectoryInfo rep = new DirectoryInfo(@"C:");

            //Thread servant à afficher les fichier trouvé par Chercher(rep);
            t = new Thread(new ThreadStart(AfficherChemin));
            t.Name = "TChemin";
            t.IsBackground = true; //mis en arrière plan pour le CPU
            t.Priority = ThreadPriority.Lowest; //toutes essayées et pas de changement
            t.Start();

            dglTxt = new SetTextBoxTextHandler(Form1.RecupText);
           
            //fonction de recherche (récurcive)
            Chercher(rep);
        }
       

        public void Chercher(DirectoryInfo Rep)
        {
            try
            {
                //récupère le chemin complet du fichier
                nomFichier = Rep.FullName;
               
                //t.Start();    //Ne fonctionne pas
              
                //dans le répertoire courant on cherche tous les fichiers
                //dont l'extension est .txt
                foreach (FileInfo f in Rep.GetFiles("*.txt"))
                {

                    //Comment faire sans message box???
                    MessageBox.Show("Chercher: " + RecupText(nomFichier));//preuve que la fonction déléguée fonctionne
                  
                    //et on on crée un item avec les chemeins et tailles de ces fichiers
                    //item qui sera ajouté à la listview
                    ListViewItem it = new ListViewItem();
                    it.Text = f.FullName;
                    it.SubItems.Add(f.Length.ToString());
                    listView1.Items.Add(it);
                }
            }
            catch { }
           
            try
            {
                //si il y a des sous répertoires on rappelle "Chercher();" (principe de la récursivité)
                DirectoryInfo[] a = Rep.GetDirectories();
                foreach (DirectoryInfo b in a)
                {
                    Chercher(b);
                }
            }
            catch { }

        }
       

        //le thread appelle cette fonction qui affiche
        //dans une textBox, tous les chemins
        //des fichiers texte sur un disque (C:).
        public void AfficherChemin()
        {
            while (true)
            {
                object[] args = new object[1];
                args[0] = nomFichier;

                //preuve que l'invocation est bonne (non ???)
                MessageBox.Show("AfficherChemin: \n\n\nInvoke: " + Invoke(dglTxt, args[0]));
                textBox1.Invoke(dglTxt, args[0]);
               
                Thread.Sleep(10);
                Application.DoEvents();
            }
        }
    }
}
0
moi411 Messages postés 179 Date d'inscription samedi 22 novembre 2003 Statut Membre Dernière intervention 25 juin 2017 3
9 juil. 2007 à 22:27
Re (dernière fois),
Ok je prends note et te remercie, j'ai continuer le programme (le code ici n'est qu'une partie) et tout fonctionne...
A la prochaine!
0
moi411 Messages postés 179 Date d'inscription samedi 22 novembre 2003 Statut Membre Dernière intervention 25 juin 2017 3
9 juil. 2007 à 22:30
moi
0
TeBeCo Messages postés 467 Date d'inscription lundi 24 juin 2002 Statut Membre Dernière intervention 9 mars 2011
10 juil. 2007 à 08:16
c'est surtout un problème de sécurité,
quand un formulaire se créé la procedure de création et initialisation des controle et realisé par un thread, il peux etre relevable en mettant un point d'arret a cet endroit la et en mettant dans l'espion express :
threading.thread.currentthread.threadID
Pour imager un peu le formulaire retient ce numéro de thread et a chaque tentative de modification de controle il compare le threadID "créateur" avec le threadID du thread tentant de modifier le controle, si ce n'est pas le même il lève une exception (ou en tout cas "est censé") de sécurité pour evité de faire des injection par exemple
c'est donc une question de sécurité plus qu'autre chose, d'ailleurs si on regarde le nom de l'exception levé : "SecurityPermissionException" ou qqchs de similaire me semble

TeBeCo
0
moi411 Messages postés 179 Date d'inscription samedi 22 novembre 2003 Statut Membre Dernière intervention 25 juin 2017 3
10 juil. 2007 à 18:49
        Bonjour,
Effectivement je n'y avais pas pensé...
Donc pour résumer (et surtout pour voir si j'ai compris), on peut dire que d'une certaine manière, la délégation fait un lien entre mes 2 threads (celui qui crée le controle et celui qui utilise le control) de façon à éviter les conflits.
Bref je crois que j'ai compris... j'espère!
Merci pour tout.
0
TeBeCo Messages postés 467 Date d'inscription lundi 24 juin 2002 Statut Membre Dernière intervention 9 mars 2011
10 juil. 2007 à 18:52
c'est a peu pret ca :p
apres les delgué en general servent pas que a ca non plus

pour plus de detail je t'invite a parcourir la doc msdn qui en dira vraiment bcp plus sur leur role dans ce cas precis et en general

TeBeCo
0
Rejoignez-nous