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 :

Chaque Thread controle une ProgressBar crée dans un Form parent ?


Sujet :

C#

  1. #1
    Membre expérimenté Avatar de Lorenzo77
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    1 472
    Détails du profil
    Informations personnelles :
    Âge : 52
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2006
    Messages : 1 472
    Points : 1 537
    Points
    1 537
    Par défaut Chaque Thread controle une ProgressBar crée dans un Form parent ?
    salut !

    je viens de finir la partie difficile de mon petit projet, c'est un client FTP multi-Thread ou chaque Thread peut envoyer un fichier vers un FTP ...
    plutot que d'avoir un Thread qui contrôle les autres Thread j'ai utilisé un Timer ce qui m'a énormément facilité la mise en place de cette partie "difficile" !

    maintenant il reste un problème :
    j'aimerais que chaque Thread puisse créer une ProgressBar dans un formulaire prévu a cette effet et met a jour la ProgressBar avec le pourcentage du fichier envoyé ... sauf qu'a la création de ma ProgressBar dans le 1er Thread j'ai cette erreur :
    Les contrôles créés sur un thread ne peuvent pas être parents d'un contrôle d'un autre thread.

    je ne vois pas quoi faire, vous avez une idée ?
    merci
    Le plus grand arbre est né d'une graine menue, une tour de neuf étages est partie d'une poignée de terre.
    Mon blog : http://web.codeur.free.fr

  2. #2
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    88
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 88
    Points : 81
    Points
    81
    Par défaut
    Bonjour,

    Il me semble que les règles d'action d'un thread sur une form sont très strictes.

    En gros, si tu as dans une meme form n ProgressBar et que tu veux que chacun d'entre eux soit controlé par un thread séparé (je crois que c'est ce que tu veux faire) tu dois passer par des délégués que tu appelles depuis tes threads.

    En gros chaque thread possède un délégué sur une méthode de la form qui permet de mettre à jour l'état des ProgressBar. Ensuite il ne te reste plus qu'à pouvoir identifier quelle ProgressBar tu veux updater quand tu appelles la méthode (mais ce n'est pas bien compliqué).

    Voila, j'espère que ça répond à ta question.

  3. #3
    Expert éminent
    Avatar de StormimOn
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2005
    Messages
    2 593
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Sarthe (Pays de la Loire)

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

    Informations forums :
    Inscription : Mai 2005
    Messages : 2 593
    Points : 7 660
    Points
    7 660
    Par défaut
    Seul le thread principal de l'application peut accéder à la partie graphique (thread de l'UI). Les autres threads n'ont pas le droit de toucher à ça, verboten

    Pour faire ce que tu veux il faut passer par l'invocation. Les méthodes de ton formulaire ressembleront à ça, au prototype de la méthode près évidemment
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public delegate void MaMethodeCallBack();
    public void MaMethode()
    {
        // this représente un contrôle (Form, UserControl, ...)
        if (this.InvokeRequired)
        {
            this.Invoke(new MaMethodeCallBack(MaMethode));
        }
        else
        {
           // Traitement ici
        }
    }
    Tu peux maintenant appeler MaMethode depuis n'importe quel thread sans aucun risque.
    Pas de questions techniques par MP

  4. #4
    Membre expérimenté Avatar de Lorenzo77
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    1 472
    Détails du profil
    Informations personnelles :
    Âge : 52
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2006
    Messages : 1 472
    Points : 1 537
    Points
    1 537
    Par défaut
    merci les gars !
    je suis bon pour reprogrammer toute la partie Thread de l'application
    c'est justement cette partie qui m'a demandé le plus d'efforts

    pas grave, ca me forcera a faire quelque chose de propre car pour l'instant j'oserais même pas la montrer alors que toute cette appli est censé finir sur sourceforge ou googlecode
    Le plus grand arbre est né d'une graine menue, une tour de neuf étages est partie d'une poignée de terre.
    Mon blog : http://web.codeur.free.fr

  5. #5
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    Une autre méthode, un peu plus simple, est d'utiliser des BackgroundWorker (BGW) à la place des threads. Dans l'évènement DoWork du BGW, tu fais le traitement, et tu appelles régulièrement ReportProgress, ce qui déclenche l'évènement ProgressChanged. Comme cet évènement est généré sur le thread de l'UI (du moins, sur le thread qui a démarré le BGW), tu peux mettre à jour tes progressbars dans le handler de cet évènement. Le BGW gère aussi l'annulation. Ca donne quelque chose comme ça :
    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
     
    // Exécuté sur le thread de l'UI
    public void DémarrerTache()
    {
        BackgroundWorker bgw = new BackgroundWorker();
        bgw.WorkerSupportsCancellation = true;
        bgw.WorkerReportsProgress = true;
        bgw.DoWork += bgw_DoWork;
        bgw.ProgressChanged += bgw_ProgressChanged;
        bgw.RunWorkerCompleted += bgw_RunWorkerCompleted;
        bgw.RunWorkerAsync();
    }
     
    // Exécuté sur un autre thread
    private void bgw_DoWork(object sender, DoWorkEventArgs e)
    {
        while(!bgw.CancellationPending && traitementPasFini)
        {
            // traitement
            ...
            bgw.ReportProgress(10); // 10%
            ...
            bgw.ReportProgress(20); // 20%
            ...
            // L'exception sera récupérée dans l'évènement  RunWorkerCompleted
            if (probleme) throw new Exception("oups");
            ...
        }
        e.Cancel = bgw.CancellationPending;
        e.Result = le_resultat_du_traitement;
    }
     
    // Exécuté sur le thread de l'UI
    private void bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        progBar.Value = e.ProgressPercentage;
    }
     
    // Exécuté sur le thread de l'UI
    private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (e.Error != null) // Si une exception s'est produite dans DoWork
        {
            MessageBox.Show("Une erreur s'est produite : " + e.Error.Message);
        }
        else if (e.Cancelled)
        {
            MessageBox.Show("Le traitement a été annulé");
        }
        else
        {
            MessageBox.Show("Traitement terminé ! Résultat : " + e.Result);
        }
    }

  6. #6
    Membre expérimenté Avatar de Lorenzo77
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    1 472
    Détails du profil
    Informations personnelles :
    Âge : 52
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2006
    Messages : 1 472
    Points : 1 537
    Points
    1 537
    Par défaut
    je viens de lire la DOC concernant la classe BackgroundWorker et elle a vraiment l'air beaucoup plus simple que les Thread.

    je vais faire des tests, merci
    Le plus grand arbre est né d'une graine menue, une tour de neuf étages est partie d'une poignée de terre.
    Mon blog : http://web.codeur.free.fr

  7. #7
    Membre expérimenté Avatar de Lorenzo77
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    1 472
    Détails du profil
    Informations personnelles :
    Âge : 52
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2006
    Messages : 1 472
    Points : 1 537
    Points
    1 537
    Par défaut
    salut,


    j'ai fait un projet de test avec vos remarques.
    je tombe toujours sur le même problème pourtant j'ai utilisé un délégué + event pour l'éviter :
    Opération inter-threads non valide : le contrôle 'dataGridView1' a fait l'objet d'un accès à partir d'un thread autre que celui sur lequel il a été créé.
    je suis obligé de laisser CheckForIllegalCrossThreadCalls = false; pour éviter cette erreur.

    vous pouvez me dire si j'ai bien utilisé ce qu'il fallait, la ou il le fallait ?
    et de la bonne manière ?

    merci


    le projet VS2008 complet (20Ko)
    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
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Threading;
    using System.Windows.Forms;
     
     
    namespace test_BackgroundWorker
    {
     
     
        public partial class Form1 : Form
        {
            private int _indexBw = 0;
            private List<object> listBw;
     
     
     
     
            public Form1()
            {
                InitializeComponent();
            }
     
            private void Form1_Load(object sender, EventArgs e)
            {
                //CheckForIllegalCrossThreadCalls = false;
                listBw = new List<object>();
            }
     
            private void Form1_FormClosing(object sender, FormClosingEventArgs e)
            {
                // faudrait une tempo plutot que de bloquer la fermeture s'il reste des "bw.IsBusy" en attendant qu'ils soient fermés ..
                for (int i = 0; i < listBw.Count; i++) {
                    BackgroundWorker bw = listBw[i] as BackgroundWorker;
                    if (bw.IsBusy == true) {
                        (listBw[i] as BackgroundWorker).CancelAsync();
                        e.Cancel = true;
                    }
                }
            }
     
            private void LancerProcessLong_Click(object sender, EventArgs e)
            {
                ProcessLong proc = new ProcessLong();
                ProcessLong.form = this;
                proc.idBw = _indexBw++;
                proc.eventCreaLigne += new ProcessLong.creaLigneHandler(proc_eventCreaLigne);
                proc.eventMajLigne += new ProcessLong.majLigneHandler(proc_eventMajLigne);
                toolStripTextBox1.Text = _indexBw.ToString();
     
                BackgroundWorker bw = new BackgroundWorker();
                listBw.Add(bw);
                bw.WorkerReportsProgress = true;
                bw.WorkerSupportsCancellation = true;
                bw.DoWork += new DoWorkEventHandler(proc.procDoWork);
                bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(proc.procComplet);
                bw.ProgressChanged += new ProgressChangedEventHandler(proc.procProgressChange);
                bw.RunWorkerAsync();
            }
     
            private void AnnulerPremier_Click(object sender, EventArgs e)
            {
                for (int i = 0; i < listBw.Count; i++) {
                    BackgroundWorker bw = listBw[i] as BackgroundWorker;
                    if (bw.IsBusy == true) {
                        (listBw[i] as BackgroundWorker).CancelAsync();
                        break;
                    }
                }
            }
     
            private void AnnulerDernier_Click(object sender, EventArgs e)
            {
                (listBw[(listBw.Count - 1)] as BackgroundWorker).CancelAsync();
                for (int i = listBw.Count - 1; i >= 0; i--) {
                    BackgroundWorker bw = listBw[i] as BackgroundWorker;
                    if (bw.IsBusy == true) {
                        (listBw[i] as BackgroundWorker).CancelAsync();
                        break;
                    }
                }
            }
     
            private void StopperTout_Click(object sender, EventArgs e)
            {
                for (int i = 0; i < listBw.Count; i++) {
                    BackgroundWorker bw = listBw[i] as BackgroundWorker;
                    if (bw.IsBusy == true) {
                        (listBw[i] as BackgroundWorker).CancelAsync();
                    }
                }
            }
     
     
     
            private void proc_eventMajLigne(object sender, int indexLigne, object chaine)
            {
                dataGridView1[0, indexLigne].Value = chaine;
            }
     
            private int proc_eventCreaLigne(object sender, object chaine)
            {
                return dataGridView1.Rows.Add(chaine);
            }
        }
     
     
     
     
        public class ProcessLong
        {
            public delegate int creaLigneHandler(object sender, object chaine);
            public delegate void majLigneHandler(object sender, int indexLigne, object chaine);
     
            public event creaLigneHandler eventCreaLigne;
            public event majLigneHandler eventMajLigne;
     
     
     
            // valeur a incrémenter
            private int _valeur = 0;
     
            // ID BackgroundWorker
            private int _idBw;
            public int idBw { get { return _idBw; } set { _idBw = value; } }
     
            // formulaire parent -> obliger d'utiliser une référence pour y accéder ?
            private static Form1 _form;
            public static Form1 form { get { return _form; } set { _form = value; } }
     
            // index DataGrid pour ce BackgroundWorker
            private int _indexDtg;
            public int indexDtg { get { return _indexDtg; } set { _indexDtg = value; } }
     
     
     
     
            public void procDoWork(object sender, DoWorkEventArgs e)
            {
                //Console.WriteLine("work debut{0} : {1}", this._idBw, this._valeur);
                _indexDtg = this.eventCreaLigne(this, "work debut(" + _idBw.ToString() + ") : " + _valeur.ToString());
                BackgroundWorker worker = sender as BackgroundWorker;
                while (worker.CancellationPending == false && _valeur < 5000) {
                    Thread.Sleep(1);
                    worker.ReportProgress(_valeur);
                    _valeur++;
                }
            }
     
            public void procComplet(object sender, RunWorkerCompletedEventArgs e)
            {
                if (e.Error != null) {
                    //Console.WriteLine("work ERREUR{0} : {1}", this._idBw, this._valeur);
                    this.eventMajLigne(this, _indexDtg, "work ERREUR(" + _idBw.ToString() + ") : " + _valeur.ToString());
                }
                else if (e.Cancelled == true) {
                    //Console.WriteLine("work ANNULÉ{0} : {1}", this._idBw, this._valeur);
                    this.eventMajLigne(this, _indexDtg, "work ANNULÉ(" + _idBw.ToString() + ") : " + _valeur.ToString());
                }
                else {
                    //Console.WriteLine("work fini{0} : {1}", this._idBw, this._valeur);
                    this.eventMajLigne(this, _indexDtg, "work FINI(" + _idBw.ToString() + ") : " + _valeur.ToString());
                }
            }
     
            public void procProgressChange(object sender, ProgressChangedEventArgs e){
                //Console.WriteLine("work en cours{0} : {1}", this._idBw, this._valeur);
                this.eventMajLigne(this, _indexDtg, "work en cours(" + _idBw.ToString() + ") : " + _valeur.ToString());
            }
        }
    }
    Le plus grand arbre est né d'une graine menue, une tour de neuf étages est partie d'une poignée de terre.
    Mon blog : http://web.codeur.free.fr

  8. #8
    Expert éminent
    Avatar de StormimOn
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2005
    Messages
    2 593
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Sarthe (Pays de la Loire)

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

    Informations forums :
    Inscription : Mai 2005
    Messages : 2 593
    Points : 7 660
    Points
    7 660
    Par défaut
    La raison pour laquelle ça ne fonctionne pas est très très simple

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public void procDoWork(object sender, DoWorkEventArgs e)
    {
        //Console.WriteLine("work debut{0} : {1}", this._idBw, this._valeur);
        _indexDtg = this.eventCreaLigne(this, "work debut(" + _idBw.ToString() + ") : " + _valeur.ToString());
        BackgroundWorker worker = sender as BackgroundWorker;
        while (worker.CancellationPending == false && _valeur < 5000) {
            Thread.Sleep(1);
            worker.ReportProgress(_valeur);
            _valeur++;
        }
    }
    Tu déclenches un événement dans le traitement du thread (DoWord) qui va modifier ton DataGridView. Donc appel inter-thread cherchant à modifier l'interface graphique et donc ça grogne.

    Version simple pour régler le problème. Change la méthode Form1.proc_eventCreaLigne ainsi
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public delegate int creaLigneHandlerCallback(object sender, object chaine);
    private int proc_eventCreaLigne(object sender, object chaine)
    {
        if (this.InvokeRequired)
        {
            return (int)this.Invoke(new creaLigneHandlerCallback(proc_eventCreaLigne), sender, chaine);
        }
        else
        {
            return dataGridView1.Rows.Add(chaine);
        }
    }
    Sinon :

    - tu devrais regarder un peu les standards sur la création d'événements (les génériques simplifiant la syntaxe maintenant), car bien que cela fonctionne ce n'est généralement pas la façon de procéder (utilisation des EventArgs, ...).

    - utiliser une List<object> c'est utiliser les génériques pour rien, autant prendre une ArrayList à ce moment. Dans ton cas c'est uneList<BackgroundWorker> qu'il faut utiliser pour éviter les cast inutiles par la suite.

    - CheckForIllegalCrossThreadCalls = false doit uniquement être utilisé pour aider pendant la phase de débogage, afin de comprendre et résoudre ce type d'erreurs.

    - ta classe ProcessLong ne devrait pas avoir connaissance du BackGroundWorder, du DataGridView ou de la Form. La seule chose importante c'est que ProcessLong doit faire un traitement et fournir des événements pour informer l'extérieur de la progression de ce traitement. Charge ensuite à l'extérieur de traiter l'information et de l'afficher comme bon lui semble.


    Une version modifiée de ton source. C'est fait comme ça, donc c'est plus un nouveau départ que quelque chose de finalisé. En plus j'ai utilisé pas mal de collections différentes alors qu'en 3.5 avec Linq et cie on doit pouvoir faire mieux
    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
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Threading;
    using System.Windows.Forms;
     
    namespace test_BackgroundWorker
    {
        public partial class Form1 : Form
        {
            private List<ProcessLong> _process;
            private Dictionary<ProcessLong, BackgroundWorker> _processWorker;
            private Dictionary<BackgroundWorker, ProcessLong> _workerProcess;
            private Dictionary<ProcessLong, int> _processRow;
     
            public Form1()
            {
                InitializeComponent();
            }
     
            private void Form1_Load(object sender, EventArgs e)
            {
                _process = new List<ProcessLong>();
                _processWorker = new Dictionary<ProcessLong, BackgroundWorker>();
                _workerProcess = new Dictionary<BackgroundWorker, ProcessLong>();
                _processRow = new Dictionary<ProcessLong, int>();
            }
     
            private void Form1_FormClosing(object sender, FormClosingEventArgs e)
            {
                e.Cancel = CancelProcess(CancelMode.All);
            }
     
            private void LancerProcessLong_Click(object sender, EventArgs e)
            {
                ProcessLong proc = new ProcessLong();
                proc.Progress += new EventHandler<ProcProgressEventArgs>(proc_Progress);
     
                BackgroundWorker bw = new BackgroundWorker();
                bw.WorkerReportsProgress = true;
                bw.DoWork += new DoWorkEventHandler(proc.DoWork);
                bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
                bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
     
                _processWorker.Add(proc, bw);
                _workerProcess.Add(bw, proc);
                _process.Add(proc);
     
                bw.RunWorkerAsync();
            }
     
            void proc_Progress(object sender, ProcProgressEventArgs e)
            {
                _processWorker[(ProcessLong)sender].ReportProgress(e.Progression, sender);
            }
     
            void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
            {
                ProcessLong process = e.UserState as ProcessLong;
     
                if (_processRow.ContainsKey(process))
                {
                    dataGridView1[2, _processRow[process]].Value = e.ProgressPercentage;
                }
                else
                {
                    _processRow[process] = dataGridView1.Rows.Add("work en cours", process.GetHashCode(), e.ProgressPercentage);
                }
            }
     
            void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                ProcessLong proc = _workerProcess[(BackgroundWorker)sender];
     
                if (e.Error != null)
                {
                    dataGridView1[0, _processRow[proc]].Value = "work ERREUR";
                }
                else if (proc.Cancelled)
                {
                    dataGridView1[0, _processRow[proc]].Value = "work ANNULE";
                }
                else
                {
                    dataGridView1[0, _processRow[proc]].Value = "work FINI";
                }
     
            }
     
     
            private void StopperTout_Click(object sender, EventArgs e)
            {
                CancelProcess(CancelMode.All);
            }
     
            private void AnnulerPremier_Click(object sender, EventArgs e)
            {
                CancelProcess(CancelMode.First);
            }
     
            private void AnnulerDernier_Click(object sender, EventArgs e)
            {
                CancelProcess(CancelMode.Last);
            }
     
            enum CancelMode { All, First, Last }
            private bool CancelProcess(CancelMode cancelMode)
            {
                bool cancel = false;
     
                if (cancelMode == CancelMode.All || cancelMode == CancelMode.First)
                {
                    foreach (ProcessLong process in _process)
                    {
                        if (_processWorker[process].IsBusy)
                        {
                            process.Cancel();
                            cancel = true;
                            if (cancelMode == CancelMode.First) { break; }
                        }
                    }
                }
                else
                {
                    for (int i = _process.Count - 1; i >= 0; i--)
                    {
                        if (_processWorker[_process[i]].IsBusy)
                        {
                            _process[i].Cancel();
                            break;
                        }
                    }
                }
     
                return cancel;
            }
        }
     
        public class ProcessLong
        {
            public event EventHandler<ProcProgressEventArgs> Progress;
     
            public bool Cancelled { get; private set; }
     
            public void DoWork(object sender, DoWorkEventArgs e)
            {
                int valeur = 0;
                while (!this.Cancelled && valeur++ < 5000)
                {
                    Thread.Sleep(1);
                    OnProgress(valeur);
                }
            }
     
            public void Cancel()
            {
                this.Cancelled = true;
            }
     
            private void OnProgress(int progression)
            {
                if (Progress != null)
                {
                    Progress(this, new ProcProgressEventArgs(progression));
                }
            }
        }
     
        public class ProcProgressEventArgs : EventArgs
        {
            public int Progression { get; private set; }
     
            public ProcProgressEventArgs(int progression)
            {
                this.Progression = progression;
            }
        }
    }
    Pas de questions techniques par MP

  9. #9
    Membre expérimenté Avatar de Lorenzo77
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    1 472
    Détails du profil
    Informations personnelles :
    Âge : 52
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2006
    Messages : 1 472
    Points : 1 537
    Points
    1 537
    Par défaut
    salut storminon

    il est génial ton exemple, je suis encore en pleine analyse

    - tu devrais regarder un peu les standards sur la création d'événements (les génériques simplifiant la syntaxe maintenant), car bien que cela fonctionne ce n'est généralement pas la façon de procéder (utilisation des EventArgs, ...).
    oui, j'ai vu dans la DOC qu'il était préférable d'étendre EventArgs, mais comme c'était juste un test je me suis dis que je pouvais zapper cette partie ...

    - utiliser une List<object> c'est utiliser les génériques pour rien, autant prendre une ArrayList à ce moment. Dans ton cas c'est uneList<BackgroundWorker> qu'il faut utiliser pour éviter les cast inutiles par la suite.
    je pensais que List<quelquechose> ne fonctionnait qu'avec les types primitifs
    ton utilisation de Dictionary<clé, val> est très intéressante, j'ai encore jamais utilisé cette classe ... va falloir

    - ta classe ProcessLong ne devrait pas avoir connaissance du BackGroundWorder, du DataGridView ou de la Form. La seule chose importante c'est que ProcessLong doit faire un traitement et fournir des événements pour informer l'extérieur de la progression de ce traitement. Charge ensuite à l'extérieur de traiter l'information et de l'afficher comme bon lui semble.
    je sais bien, j'essaye mais c'est pas simple a mettre en place, il me manque encore beaucoup de connaissances


    merci
    Le plus grand arbre est né d'une graine menue, une tour de neuf étages est partie d'une poignée de terre.
    Mon blog : http://web.codeur.free.fr

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

Discussions similaires

  1. Thread avec une progressBar
    Par barbiche dans le forum AWT/Swing
    Réponses: 1
    Dernier message: 09/10/2007, 00h12
  2. reprendre une hash crée dans un sous programme
    Par fripette dans le forum Langage
    Réponses: 11
    Dernier message: 07/08/2007, 15h05
  3. Réponses: 8
    Dernier message: 17/05/2007, 19h29
  4. Colorer chaque mot par une couleur differente dans un champ de texte
    Par Mettali hedi dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 25/01/2007, 13h20
  5. Réponses: 6
    Dernier message: 02/10/2006, 12h13

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