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 :

[Débutant] Problème de thread


Sujet :

C#

  1. #1
    Membre à l'essai
    Inscrit en
    Avril 2008
    Messages
    45
    Détails du profil
    Informations forums :
    Inscription : Avril 2008
    Messages : 45
    Points : 22
    Points
    22
    Par défaut [Débutant] Problème de thread
    Bonjour,

    Ça à l'air d'être un problème courant et j'ai beau lire les tutos, je n'arrive pas à résoudre mon problème (je pense l'avoir compris, c'est déjà ça...).

    En fait, j'ai une fonction pour tester l'état d'un serveur qui renvoie un booléen si il est disponible ou non.
    De là je veux modifier des icônes des des labels d'un contrôle.
    Pas compliqué donc..
    Sauf que le timeout de ma fonction est assez long et j'aimerais le faire en tâche de fond pour ne pas figer ma form..

    Du coup j'ai essayé ca:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
                Thread _threadStatusServer;
                _threadStatusServer = new Thread(new ThreadStart(status_server));
                _threadStatusServer.Name = "ThreadStatutServeur";
                _threadStatusServer.Start();
    Mais j'obtiens une erreur:
    Les contrôles créés sur un thread ne peuvent pas être parents d'un contrôle d'un autre thread
    Ou alors:

    [...] fait l'objet d'un accès à partir d'un thread autre que celui sur lequel il a été créé.
    Et parfois ca fonctionne très bien... :/ c'est aléatoire.

    Alors j'ai essayé de le faire avec un backgroundWorker, je l'ajoute à ma Form puis je fais:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    backgroundWorkerServeur.RunWorkerAsync(b = Serveur.TestStatut());
    Mais là il ne l'exécute même pas en tâche de fond :/

    Ma fonction TestStatut est celle avec le timeout et la procédure status_serveur est celle qui appelle TestStatut et modifie les label et icônes.


    Donc, d'après ce que j'ai compris, quand je fais mon thread, il n'aurait pas de parent (qui devrait être ma form?) donc il ne peut pas modifier les controles?

    De là j'ai lu plein de tuto qui m'ont trop embrouillés avec des délégué et compagnie, c'est pour ca que je viens vous voir, pour avoir une version plus explicite et personnalisée de mon problème et peut-être une aide pour le résoudre

    Merci d'avance à ceux qui me liront!

    Cdlt

  2. #2
    Membre émérite Avatar de Guulh
    Homme Profil pro
    Inscrit en
    Septembre 2007
    Messages
    2 160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2007
    Messages : 2 160
    Points : 2 925
    Points
    2 925
    Par défaut
    En deux mots : comme tu l'as vu, on ne peux pas modifier l'UI dans un thread métier. Or ton booléen est calculé dans un thrad métier ; il faut un moyen de trimballer ton booléen dans le thread de l'UI.

    Le plus simple est d'utiliser le backgroundworker. Il lève deux événements principaux : DoWork et RunWorkerCompleted.
    DoWork est levé dans un thread métier ; c'est là que tu vas checker le statut de ton serveur. DoWork a en paramètre un EventArgs qui contient un paramètre Result ; stocke ce booléen dans Result.
    RunWorkerCompleted est levé dans le thread de l'UI, dès que DoWork a fini. WorkCompleted a aussi un eventargs qui contient, dans sa propriété Result, la valeur assignée par le DoWork.
    Donc, grosso modo, avec un BackGroundWorker nommé bgw:
    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
    bgw.DoWork += OnDoWork;
    bgw.RunWorkerCompleted += OnRunWorkerCompeted;
    ...
    private void OnDoWork(object sender, DoWorkEventArgs e)
    {
       // ca peux prendre du temps, on s'en fiche,
       // on est dans un thread métier
       bool status = GetServerStatus();
       e.Result = status;
    }
     
    private void OnRunWorkerCompleted(object sender,RunWorkerCompletedEventArgs e)
    {
        // on récupère le booléen assigné par DoWork;
        bool status = (bool)e.Result;
        // là, t'es dans le thread de l'ui,
        // tu peux tripoter les contrôles autant que tu veux
        this.labelBidule.Text = ...
    }
    Et tu lance le worker avec un simple bgw.RunWorkerAsync().

    C'est plus clair ?
    ಠ_ಠ

  3. #3
    Membre émérite
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Avril 2006
    Messages
    1 627
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Avril 2006
    Messages : 1 627
    Points : 2 331
    Points
    2 331
    Par défaut
    Quand et où crées-tu ton thread ?

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 99
    Points : 93
    Points
    93
    Par défaut
    Si ce thread est lancé depuis un form tu ferais mieux d'utiliser un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    System.ComponentModel.BackgroundWorker
    et si je ne dis pas de betise l'évènement
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    System.ComponentModel.BackgroundWorker.RunWorkerCompleted
    est lancé dans le bon thread ce qui t'évitera cette exception.

  5. #5
    Membre à l'essai
    Inscrit en
    Avril 2008
    Messages
    45
    Détails du profil
    Informations forums :
    Inscription : Avril 2008
    Messages : 45
    Points : 22
    Points
    22
    Par défaut
    Citation Envoyé par Guulh Voir le message
    En deux mots : comme tu l'as vu, on ne peux pas modifier l'UI dans un thread métier. Or ton booléen est calculé dans un thrad métier ; il faut un moyen de trimballer ton booléen dans le thread de l'UI.

    Le plus simple est d'utiliser le backgroundworker. Il lève deux événements principaux : DoWork et RunWorkerCompleted.
    DoWork est levé dans un thread métier ; c'est là que tu vas checker le statut de ton serveur. DoWork a en paramètre un EventArgs qui contient un paramètre Result ; stocke ce booléen dans Result.
    RunWorkerCompleted est levé dans le thread de l'UI, dès que DoWork a fini. WorkCompleted a aussi un eventargs qui contient, dans sa propriété Result, la valeur assignée par le DoWork.
    Donc, grosso modo, avec un BackGroundWorker nommé bgw:
    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
    bgw.DoWork += OnDoWork;
    bgw.RunWorkerCompleted += OnRunWorkerCompeted;
    ...
    private void OnDoWork(object sender, DoWorkEventArgs e)
    {
       // ca peux prendre du temps, on s'en fiche,
       // on est dans un thread métier
       bool status = GetServerStatus();
       e.Result = status;
    }
     
    private void OnRunWorkerCompleted(object sender,RunWorkerCompletedEventArgs e)
    {
        // on récupère le booléen assigné par DoWork;
        bool status = (bool)e.Result;
        // là, t'es dans le thread de l'ui,
        // tu peux tripoter les contrôles autant que tu veux
        this.labelBidule.Text = ...
    }
    Et tu lance le worker avec un simple bgw.RunWorkerAsync().

    C'est plus clair ?
    Yeah! Ça fonctionne nickel!
    Et j'ai tout compris!
    En fait, le backgroundWorker n'était pas aussi intuitif que ce j'imaginais et ce que montrait les tutos mais j'ai mieux compris le fonctionnement maintenant et j'ai bien envie d'en mettre à plein d'endroits où je faisais des thread ^^
    Maintenant que j'ai pigé le truc, je trouve ca carrément plus propre que de faire des thread à la main :S non?
    On peut même faire des bargraph à ce que j'ai vu aussi, sympa!

    Merci beaucoup aux autres réponses aussi! et pour la rapidité!
    C'est génial ici

    Cdlt
    Jerem

  6. #6
    Membre émérite Avatar de Guulh
    Homme Profil pro
    Inscrit en
    Septembre 2007
    Messages
    2 160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2007
    Messages : 2 160
    Points : 2 925
    Points
    2 925
    Par défaut
    Citation Envoyé par jeremdu94 Voir le message
    Maintenant que j'ai pigé le truc, je trouve ca carrément plus propre que de faire des thread à la main :S non?
    Au final c'est pareil, le BGW ne fait que wrapper des fonctionnalités plus bas niveau. C'est juste qu'il permet d'éviter pas mal de plomberie, s'intègre bien au designer de forms, et satisfait la plupart des besoins. Moins de code => moins de bugs

    Citation Envoyé par jeremdu94 Voir le message
    Merci beaucoup aux autres réponses aussi! et pour la rapidité!
    Au plaisir
    ಠ_ಠ

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 28/04/2004, 11h25
  2. [Débutant] Problème de déconnexion d'une page JSP
    Par amal9 dans le forum Servlets/JSP
    Réponses: 12
    Dernier message: 22/01/2004, 13h40
  3. [débutant] Problèmes avec CRegKey
    Par Pedro dans le forum MFC
    Réponses: 4
    Dernier message: 10/11/2003, 15h28
  4. Réponses: 11
    Dernier message: 02/09/2003, 14h20
  5. [VC++6][DX9] Problème de thread lors d'un blit ...
    Par grandjouff dans le forum DirectX
    Réponses: 2
    Dernier message: 12/06/2003, 22h22

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