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 :

[2.0][Threading] Arrêt et reprise de Thread


Sujet :

C#

  1. #1
    Membre du Club
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Mars 2002
    Messages
    54
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Mars 2002
    Messages : 54
    Points : 58
    Points
    58
    Par défaut [2.0][Threading] Arrêt et reprise de Thread
    Contexte

    J'ai une application dont le but est de lire des données d'une base et de les écrire dans une autre.

    Pour cela, j'ai une classe Agent composée d'un objet de la classe ReaderWrapper et un autre de la classe WriterWrapper.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    private ReaderWrapper m_ReadWrapper;
    private WriterWrapper m_WriteWrapper;
    La classe Agent est aussi composée de deux Threads : un "reader" et un "writer".
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    private Thread m_Reader;
    private Thread m_Writer;
    Chaque Thread déclenche l'exécution d'une méthode Run() de son Wrapper respectif (Reader ou Writer).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    this.m_Reader = new Thread(new ThreadStart(this.m_ReadWrapper.Run));
    this.m_Writer = new Thread(new ThreadStart(this.m_WriteWrapper.Run));
    La méthode Run() de chaque Wrapper appelle la méthode Read() ou Write() d'une classe Worker, tant que l'objet Agent n'a pas demandé l'arrêt :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    while (!this.m_Agent.Stopped) this.m_Worker.Write();
    Dans la classe Worker, les deux Threads sont synchronisés via un Monitor :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    Lock (this)
    {
    Monitor.Wait(this);
    TRAITEMENT ICI
    Monitor.Pulse(this);
    }
    Cette structure est commune à chacune des méthodes Read() et Write().


    Problème

    Quand je demande l'arrêt de l'Agent, cela fonctionne : les Theads sont suspendus :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
    Quand je demande la reprise du travail de l'Agent une 1er fois, cela fonctionne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    if (this.m_Reader.ThreadState == ThreadState.WaitSleepJoin) this.m_Reader.Interrupt();
    L'appel à la méthode Interrupt() lève une System.Threading.ThreadInterruptedException dans les classes ReaderWrapper et WriterWrapper. L'exception ets catchée puis un appel récursif reprend le travail :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    public void Run()
    {
    try
    {
    while (!this.m_Agent.Stopped) this.m_Worker.Write();
    System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
    }
    catch(System.Threading.ThreadInterruptedException) 
    {
    this.Run();
    }
    }
    Le problème, c'est que cela fonctionne la première fois seulement : seul 1 redémarage fonctionne. L'exception n'est pas levée la seconde fois et le travail ne repdrend pas.

    Je sais que c'est pas facile comme ça, mais si quelqu'u na déjà rencotnré ce cas, je suis preneur.

  2. #2
    Membre expérimenté Avatar de Mose
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 143
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 143
    Points : 1 379
    Points
    1 379
    Par défaut
    Ca sent le deadlock... ta synchro m'a pas l'air très orthodoxe...
    Essaye de mettre un timeout à ton Monitor.Wait, je serait pas étonné que ça se débloque...

  3. #3
    Membre du Club
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Mars 2002
    Messages
    54
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Mars 2002
    Messages : 54
    Points : 58
    Points
    58
    Par défaut
    Mose,

    Tout d'abord merci pour ta réponse.

    J'ai simplifié la structure du programme et n'ai plus qu'un seul Thread. Les opérations de lecture de d'écriture de données sont effectuées dans ce même Thread dans un bloc Lock : le but est d'empêcher tout nouvel appel à ces deux opérations de traitement de données tant qu'une opération est en cours.

    Agent
    |_ Wrapper : Run() --> le Thread boucle ici
    |_ Worker : Work() --> traitement dans bloc Lock

    L'agent lance un Thread qui pointe sur la méthode Run() du Wrapper. Cette méthode est une boucle qui appelle la méthode Work() du Worker.
    Quand cette propriété vaut True, on sort de cette boucle, le Thread termine son travail et meurt.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    public void Run()
            {
                while (!m_Agent.Stopped)
                {
                    m_Worker.Work(); 
                }
            }
    Par contre, j'ai toujours le même problème : après un redémarrage (start > stop > start > stop) et suite au dernier arrêt, les traces indiquent une nouvelle connexion à une base de donnée.

    Ce que j'ai omis de préciser, c'est que le C# utilise un composant "maison" C++. C'est ce composant qui signale dans les traces un nouvelle ouverture de connexion. D'autant plus navrant, puisqu'on ne repasse pas dans le code C# qui ouvre les connexions ...

    Je pense donc que ce n'est pas un problème de Threading côté C#, mais côté C++ : le composant ne doit pas être conçu pour être utilisé dans un context Threading. Je précise qu'un seul Thread tourne "à la fois".

    Mes questions
    - me confirmes-tu (comme je crois le savoir) qu'un Thread ayant terminé sa tâche meurt de lui-même ?
    - as-tu une expérience dans ce contexte C# - C++ avec utilisation de Thread ?

    Merci.

Discussions similaires

  1. [Visual C#] Reprise de threads bloqués
    Par levalp dans le forum Windows Forms
    Réponses: 4
    Dernier message: 22/02/2008, 22h25
  2. ordre de reprise de threads bloqués
    Par duaner dans le forum C#
    Réponses: 19
    Dernier message: 05/07/2007, 15h52
  3. Thread, Arrête toi je le veux !
    Par mlle lain dans le forum Concurrence et multi-thread
    Réponses: 30
    Dernier message: 17/10/2006, 14h19
  4. [win32] threads, suspension et reprise
    Par xilebo dans le forum Windows
    Réponses: 7
    Dernier message: 14/02/2006, 14h24
  5. pause et reprise de thread
    Par raggadoll dans le forum C++Builder
    Réponses: 5
    Dernier message: 12/07/2003, 10h50

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