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

Framework .NET Discussion :

Mutex, thread et event


Sujet :

Framework .NET

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 5
    Par défaut Mutex, thread et event
    Bonjour,

    Ayant cherché pas mal et n'ayant pas trouvé de réponses satisfaisantes, je me permet de poser mon problème ici, en espérant qu'un âme charitable trouve une solution.

    Donc j'ai un control avec une event KeyDown, et je veux déclencher une action quand deux touches précises sont enfoncées simultanément.

    voici le code:

    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
           private void globalEventProvider1_KeyDown(object sender, KeyEventArgs e)
           {
               if (e.KeyCode == keyOne)
               {
                   KeyOnePressed = true;
               }
               if (e.KeyCode == keyTwo)
               {
                   KeyTwoPressed = true;
               }
               if (e.KeyCode == keyOne ||e.KeyCode == keyTwo)
               {
                         var t = new Thread(criticalSection);
                         t.Start();
                         t.Join();
               }
     
           }
     
           private static Semaphore sem = new Semaphore(1, 1);
     
           private void criticalSection()
           {
               sem.WaitOne();
               if (KeyOnePressed && KeyTwoPressed)
               {
                   KeyOnePressed = false;
                   KeyTwoPressed = false;
                   MessageBox.Show("OK");
               }
               sem.Release();
           }

    Le problème ici est que comme vous pouvez le constater j'utilise un thread séparé pour l'action finale.

    J'en suis arrivé la car si je met le code de ce thread directement dans la première fonction, la message box se lance toujours deux fois.

    J'ai essayer de protéger se morceau de code avec un lock, un mutex, rien n'y fait.

    Si on appui sur deux touches en simultané, deux threads se lancent pour gérer les évènements des touches, ils sont différents mais pourtant les restrictions tels que le lock ou le mutex ne s'applique pas a eux.

    Comme si c'était un seul et unique thread.

    J'aimerais qu'on m'explique simplement pourquoi le lock ou le mutex ne marche pas dans ce cas précis et s'il existe une façon plus propre que mon code pour le faire.

    En passant, cela pourrait il avoir un rapport avec le nombre de coeurs du processeur ?

    Merci et bonne journée.

  2. #2
    Membre éprouvé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Avril 2006
    Messages
    1 627
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    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
    Par défaut
    Hello,

    même si tu appuies sur tes 2 touches en simultanées, tu auras toujours un léger décalage temporel (de l'ordre de la dizaine de ms), donc tu appelleras toujours ta méthode criticalSection 2 fois.

    * T1 instancié
    * T2 instancié
    * T1 obtient le mutex, il rentre dans la section critique
    * T2 juste après bloqué sur le WaitOne
    * T1 Release
    * T2 obtient mutex et re-traite
    Un seul thread d'appel doit être créé. Si tu veux en créer plusieurs, utilise return dans la section critique près avoir checké tes arguments plutôt que de faire des wait

    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
    private void globalEventProvider1_KeyDown(object sender, KeyEventArgs e)
    {
    if (e.KeyCode == keyOne)
    {
    KeyOnePressed = true;
    }
    if (e.KeyCode == keyTwo)
    {
    KeyTwoPressed = true;
    }
    if (KeyOnePressed  && KeyTwoPressed ) //on déplace le test, si on a les deux touches actives on est bons !
    {
    var t = new Thread(criticalSection);
    t.Start();
    t.Join(); //utile  ???
    }
    et tu peux virer les sémaphores de ta section critical

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 5
    Par défaut
    il manque un bout de code en fait.

    En réalité il y a un aussi un event keyup ou je met les boolean keyonepressed et keytwopressed a false.

    C'est pas exactement ce que tu crois, l'intérêt du sémaphore ici est que justement il n'autorise qu'un seul thread a faire l'action et vu que ce thread remet les deux boolean a false, quand le deuxième thread récupère le sémaphore la condition n'est plus respecté (les deux boolean sont a false) donc il n'exécute pas le code.

    C'est la seule façon que j'ai trouvé actuellement pour que le code s'exécute une seule fois.

    Si je fais comme tu me dis (car je l'ai déjà tenté), le code de la section critique sera exécuté deux fois, et c'est exactement ce que je ne veux pas.

    Si on appuie vraiment simultanément sur les deux touches, la différence entre les deux thread est d'une seule instruction, donc avant même que les variables soient remises a false les deux thread sont dans le codes critique.

    J'utilise un thread car celui ci, une fois lancé par chaque thread entrant, est bien reconnu comme différent par l'application, donc le sémaphore fonctionne.

    Si j'enlève l'appel du thread, le sémaphore ne fonctionne plus, car l'application considère les deux thread entrant dans le keypress comme un seul thread !!

    C'est la tout mon problème, j'aimerais déjà dans un premier temps comprendre comment deux thread peuvent être considérés comme un seul.

    Merci de ta réponse en tout cas.

    EDIT: je vois que tu viens d'éditer du coup tout ma réponse ne correspont plus à la tienne, je la laisse néanmoins pour le complément d'infos.
    Mais dans ta dernière édition je vois un truc auquel je n'avais pas pensé qui est surement une solution, c'est le return. Mais cela ne me donne toujours pas la réponse que je cherche.

  4. #4
    Membre éprouvé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Avril 2006
    Messages
    1 627
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    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
    Par défaut
    Le fait d'utiliser des sémaphores introduit peut-être une notion de contexte distinct, je ne sais pas là :/

    Ce qui est intéressant, c'est que tu mets tes variables à false, et derrières elles valent true. Si c'est des propriétés, tu peux tracer le get et le set, avec identifiant du thread sur chaque appel ? A mon sens c'est piger le pourquoi de ce changement des valeurs sur tes booléens

  5. #5
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 5
    Par défaut
    Je vais tenter de détailler encore plus le contexte.

    j'ai deux machines différentes:
    - une avec XP 32 bit et un core 2 duo, on l'appellera XP.
    - une avec Seven 64 bit et un phenom X3, on l'appellera Seven.
    -DotNet 3.5 sur les deux machines.
    Si l'on considère le morceau de code suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    private void textBox1_KeyDown(object sender, KeyEventArgs e)
            {
                if (e.KeyValue == 111)
                {
                    KeyOnePressed = true;
                }
                if (e.KeyValue == 106)
                {
                    KeyTwoPressed = true;
                }
                             if (KeyOnePressed && KeyTwoPressed)
                    {
    Le contexte est le suivant:
    -KeyOnePressed et KeyTwoPressed sont à false par défaut.
    -KeyValue 111 correspond a la touche [/]
    -KeyValue 106 correspond a la touche[*]

    On appuie simultanément sur[*] + [/].
    -Sur seven, deux thread s'executent en parallèle, chacun gérant un keypress.
    De ce fait le thread gerant [/] va passer KeyOnePressed a true et le thread gerant[*] va passer KeyTwoPressed a true, si bien que les deux thread vont arriver en même temps a la partie
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
                              if (KeyOnePressed && KeyTwoPressed)
                    {
    et vu que les deux boolean sont a true a cet instant, les deux thread vont entrer dans la section.

    -Sur XP, les thread s'exécutent l'un après l'autre, le premier thread gerant [/] va passer KeyOnePressed a true et en arrivant au test, la condition n'étant pas remplie ( KeyTwoPressed est false), va s'arrêter.
    Le deuxième thread gerant[*] s'execute a son tour et va passer KeyTwoPressed a true, arrivé au test, la condition est remplie, les deux boolean sont a true, il exécute le code.


    Voila tout ceci pour expliquer clairement que sur la machine XP je n'ai pas de problème, le code après la condition s'exécute une seule fois comme souhaité, mais sur la machine seven deux fois.

    Comment puis je faire pour qu'il ne s'exécute qu'une fois, de façon optimale j'entends, et surtout pourquoi je ne puis le faire sans passer par un thread intermédiaire, ce que je trouve particulièrement crade en passant.

    Je cherche plus a comprendre ce qu'il se passe dans un premier temps qu'une réelle solution, je préférait grandement savoir, puis essayer de trouver la solution par moi même.

    J'ai lu beaucoup de choses sur le net sur les thread et les processeurs multicoeur, mais je n'ai vu nulle part le lien avec les lock() ou les sémaphores.

    Si un expert dans le domaine pouvait ne serait ce que me donner des pistes de lecture, je lui en serais gré.

    Désolé pour le pavé, mais ce problème me tient a cœur.

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

    Informations forums :
    Inscription : Septembre 2007
    Messages : 2 160
    Par défaut
    Je vois pas bien pourquoi tu t'embêtes avec des threads...

    Ce que tu veux, c'est juste déclencher une action quand deux touches déterminées sont appuyées simultanément ?
    Il me semble qu'il te suffit de garder un booléen pour chaque touche, mis à true dans le keydown et à false dans le keyup, et déclencher ta méthode (l'appel de messagebox ici) uniquement si tes deux booléens sont true.
    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
    private void bidule_KeyDown(object sender, KeyEventArgs e)
    {
      if (e.KeyCode == keyOne)
        KeyOnePressed = true;
      else if (e.KeyCode == keyTwo)
        KeyTwoPressed = true;
      if (KeyOnePressed && KeyTwoPressed)
        MessageBox.Show("Victoire !");
    }
     
    private void bidule_KeyUp(object sender, KeyEventArgs e)
    {
      if (e.KeyCode == keyOne)
        KeyOnePressed = false;
      else if (e.KeyCode == keyTwo)
        KeyTwoPressed = false;
    }
    Quel rapport avec les threads ?

Discussions similaires

  1. Thread et Events
    Par arnauld dans le forum C#
    Réponses: 11
    Dernier message: 08/12/2010, 09h56
  2. Simulation de thread pour Event.COMPLETE
    Par +Guilhem dans le forum ActionScript 3
    Réponses: 3
    Dernier message: 10/03/2010, 12h25
  3. [threading]Mon event.wait() bloque.
    Par orime dans le forum Général Python
    Réponses: 0
    Dernier message: 10/02/2010, 21h22
  4. [C#] Thread et events dans une form
    Par farfadet dans le forum Windows Forms
    Réponses: 3
    Dernier message: 21/12/2006, 18h50
  5. [C#]Thread, event/delegate et Form
    Par doccpu dans le forum Windows Forms
    Réponses: 28
    Dernier message: 01/08/2005, 18h35

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