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

Windows Forms Discussion :

[C#2005] Comment utiliser le multithreading


Sujet :

Windows Forms

  1. #1
    Membre actif
    Homme Profil pro
    DBA - Développeur BI
    Inscrit en
    Avril 2003
    Messages
    442
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : DBA - Développeur BI
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2003
    Messages : 442
    Points : 283
    Points
    283
    Par défaut [C#2005] Comment utiliser le multithreading
    Bonjour,

    J'ai écumé le net sur l'utilisation des mulithreads mais je ne saisi pas bien encore son fonctionnement. Donc voici le contexte. J'ai une appli qui fait un traitement qui fige complètement ma fenêtre principale donc je me suis dis que je vais utiliser un autre thread pour effectuer ce traitement. Dans mon thread principal j'ai fais ceci:
    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
     
    public partial class frmLauncherBo : Form
        {
    private Thread _threadTraitement;
    public frmLauncherBo()
            {
                InitializeComponent();
     
            }
    private void btnProcess_Click(object sender, EventArgs e)
            {
                StartThread();
                //TraitementDoc();
            }
    private void StartThread()
            {
                //TraitementDoc est la fonction exécutée par le thread
                _threadTraitement = new Thread(new ThreadStart(TraitementDoc));
                //On nomme le thread pas obligatoire
                _threadTraitement.Name = "Traitement_doc_bo";
                //Démarrage du thread
                _threadTraitement.Start();
            }
    et lors de l'exécution j'ai le message suivant:
    Opération inter-threads non valide: le contrôle 'frmLauncherBo' a fait l'objet d'un accès d'un thread autre que celui sur lequel il a été créé.
    Alors je pense que j'ai du mal déclaré mon thread mais je ne sais pas comment.
    Faut-il créer une classe à part et l'appeler depuis mon form principal. Je précise que mon form principal s'appelle frmLauncherBo.

  2. #2
    Rédacteur
    Avatar de dev01
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    2 451
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 2 451
    Points : 6 017
    Points
    6 017
    Par défaut
    Bonjour.

    en fait la réponse est beaucoup plus simple et est contenu dans le message de l'exception.

    Vous ne pouvez pas accéder à un composant graphique (button, label, etc,) depuis un autre thread que celui ou il a été créé.

    Pour contourner ce problème il faut utiliser la méthode Invoke du control

    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
     
    public partial class frmLauncherBo : Form
        {
    private Thread _threadTraitement;
    public frmLauncherBo()
            {
                InitializeComponent();
     
            }
    private void btnProcess_Click(object sender, EventArgs e)
            {
                StartThread();
                //TraitementDoc();
            }
    private void StartThread()
            {
                //TraitementDoc est la fonction exécutée par le thread
                _threadTraitement = new Thread(new ThreadStart(TraitementDoc));
                //On nomme le thread pas obligatoire
                _threadTraitement.Name = "Traitement_doc_bo";
                //Démarrage du thread
                _threadTraitement.Start();
            }
     
            private void TraitementDoc()
            {
                  this.ChangeText
            }
     
    private delegate void InvokeHandler(string);
     
            private void ChangeText(string text)
            {
                  if( this.button1.InvokeRequired)
                      this.button1.Invoke(new InvokeHandler(ChangeText));
                  else
                      this.button1.Text = text;
            }
    - MVP C#
    -Tout problème a une solution, le vrai problème est de trouver la solution .....
    - Linux & mono : l'avenir

  3. #3
    Membre actif
    Homme Profil pro
    DBA - Développeur BI
    Inscrit en
    Avril 2003
    Messages
    442
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : DBA - Développeur BI
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2003
    Messages : 442
    Points : 283
    Points
    283
    Par défaut
    Bon je me suis penché sur le code de dev01
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    private delegate void InvokeHandler(string);
     
            private void ChangeText(string text)
            {
                  if( this.button1.InvokeRequired)
                      this.button1.Invoke(new InvokeHandler(ChangeText));
                  else
                      this.button1.Text = text;
            }
    mais je n'ai pas réussi à le tranposer à mon cas. voici ma fonction TraitementDoc:
    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
     
    DialogResult rep;
                    rep = MessageBox.Show(this, "Rafraichir le(s) document(s) sélectionné(s)", "REFRESH"
                    , MessageBoxButtons.YesNo);//Demande autorisation de rafraichir
                    if (rep == DialogResult.Yes)
                    {
                        bool opSuccess = true;
                        nbDocSelected = lbDocuments.SelectedIndices.Count;//Compte le nbre de document sélectionné
     
                        //Boucle principale compte de nbre de document sélectionné
                    for (int nbDoc = 1; nbDoc <= nbDocSelected; nbDoc++)//parcours les documents sélectionnés
                    {
                        Cursor.Current = Cursors.WaitCursor;
                        boNomDoc = lbDocuments.Text;
                        lblSuiviOp.Text = nbDocSelected.ToString()+" Rapports. Traitement du document: "+ boNomDoc;
                        nbSocieteSelected = lbSociete.SelectedIndices.Count;//Compte le nbre de société sélectionnée
                        indexDocSelected = lbDocuments.SelectedIndex;//Obtient l'index de base 0 du doc sélectionné
                        boDoc = boAppli.Documents.Open(boNomDoc,true,false,pWd,wrPwd);//Ouverture du document
    etc...
    je ne met pas tout car c'est très long

  4. #4
    Rédacteur
    Avatar de dev01
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    2 451
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 2 451
    Points : 6 017
    Points
    6 017
    Par défaut
    Et ?

    ou est le problème ? La seule chose à faire c'est de sortir tout le code qui touche de près ou de loin aux composants winform dans une fonction externe de d'y ajouter la vérification à l'aide de InvokeRequiered
    - MVP C#
    -Tout problème a une solution, le vrai problème est de trouver la solution .....
    - Linux & mono : l'avenir

  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 approche, plus simple que l'utilisation de Invoke, est d'utiliser un BackgroundWorker (BGW) plutôt qu'un thread.
    Quand tu démarres un BGW avec la méthode RunWorkerAsync, ça déclenche sur un autre thread l'évènement DoWork, dans lequel tu va faire ton traitement.
    Si le traitement a besoin de notifier l'interface utilisateur de sa progression, il le fait en appelant la méthode ReportProgress du BGW : ça déclenche l'évènement ProgressChanged sur le thread principal, donc dans cet évènement tu peux mettre à jour l'interface.
    Quand le traitement se termine, l'évènement RunWorkerCompleted se produit sur le thread principal : tu peux récupérer le résultat du traitement et mettre à jour l'interface.

    La seule contrainte à respecter est de ne pas accéder à l'interface graphique directement à partir du code de l'évènement DoWork, car il est exécuté dans un autre thread

  6. #6
    Membre actif
    Homme Profil pro
    DBA - Développeur BI
    Inscrit en
    Avril 2003
    Messages
    442
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : DBA - Développeur BI
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2003
    Messages : 442
    Points : 283
    Points
    283
    Par défaut
    bon je pense avoir compris les deux méthodes.
    Ce qu'il faut que je fasse comme l'a dit Dev01 c'est retirer tout appel à un composant de ma form
    ex : dans ma form lbDocuments est une listbox donc j'ai le code suivant dans ma fonction:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    int nbDocSelected=lbDocuments.SelectedIndices.Count;
    dans les 2 cas(multithreading et BGW) je dois passer ces informations en paramêtre. Est-ce que c'est bien sa?
    C'est la première fois que je fais ce genre d'appli donc soyez indulgent avec mon ignorance.

  7. #7
    Rédacteur
    Avatar de dev01
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    2 451
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 2 451
    Points : 6 017
    Points
    6 017
    Par défaut
    Citation Envoyé par Herlece Voir le message
    bon je pense avoir compris les deux méthodes.
    Ce qu'il faut que je fasse comme l'a dit Dev01 c'est retirer tout appel à un composant de ma form
    ex : dans ma form lbDocuments est une listbox donc j'ai le code suivant dans ma fonction:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    int nbDocSelected=lbDocuments.SelectedIndices.Count;
    dans les 2 cas(multithreading et BGW) je dois passer ces informations en paramêtre. Est-ce que c'est bien sa?
    C'est la première fois que je fais ce genre d'appli donc soyez indulgent avec mon ignorance.
    C'est bien ça. Après peu importe la méthode choisie pour utiliser les threads, la base reste la même : Pas d'utilisation de l'UI dans un thread
    - MVP C#
    -Tout problème a une solution, le vrai problème est de trouver la solution .....
    - Linux & mono : l'avenir

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

Discussions similaires

  1. Comment utiliser le multithread dans mon cas?
    Par Vanito dans le forum Général Dotnet
    Réponses: 12
    Dernier message: 04/10/2012, 09h39
  2. SSIS 2005 : comment utiliser un chemin reseau?
    Par jpcre dans le forum SSIS
    Réponses: 2
    Dernier message: 09/11/2011, 11h26
  3. [2005] Comment Utiliser 2 'CURSORS'
    Par Cyrille36 dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 03/04/2009, 09h26
  4. Réponses: 2
    Dernier message: 24/04/2008, 18h26
  5. [VS 2005] Comment définir la version du framework à utiliser?
    Par therock dans le forum Visual Studio
    Réponses: 1
    Dernier message: 04/08/2006, 06h08

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