Interface Graphique qui fige mes threads

GreensourceGreensource Membre
novembre 2009 modifié dans API AppKit #1
Bonjour!
J'ai un souci avec mon interface graphique. Lorsque je clique dedans, mon application ce fige. En temps normal, j'ai un Thread qui régulièrement vient regarder la valeur d'un NSSlider, or dès que je clique sur le Slider, le Thread se met en pause.
Je sais que le slider peut directement rendre sa valeur mais on a un TP où l'ont est obliger de faire ça.

Petite précision, j'utilise un NSTimer, pas directement un Thread, mais il me semblais qu'un NSTimer avais son propre run loop non? Sinon ça peut provenir de ça.

Vous avez une idée?

ps: J'ai l'impression d'avoir déjà  posé cette question? ^^Je vais vérifier

[edit] bas non ça devais être dans ma tête...

Réponses

  • AliGatorAliGator Membre, Modérateur
    21:55 modifié #2
    Un Thread et un Timer ne sont pas la même chose, ils ne fonctionnent pas sur la même base.

    Un Timer s'installe sur la RunLoop du thread sur laquelle tu l'as "schedulé". En l'occurrence donc avec ta solution, tu n'as qu'un seul thread, et tu as installé un timer sur la RunLoop de ce thread principal (et unique), et à  chaque bouclage de la RunLoop, ça va vérifier si parmi les timers qui sont installés il y en a à  déclencher, et si oui va exécuter leur méthode, avant de continuer la runloop normalement.
    C'est donc normal si tu utilises un Timer que ce soit bloquant, ce n'est pas exécuté dans un thread séparé.

    Par contre si tu migres vers un thread, n'oublies pas de protéger l'accès à  la variable du slider par mutex, le plus simple étant d'avoir un "getter" qui utilise @synchronized(self) pour protégrer l'accès concurrenciel à  la valeur du slider par plusieurs threads.
  • GreensourceGreensource Membre
    21:55 modifié #3
    Okay, c'est logique. Donc un Timer ne lance pas de Thread, je pensais pourtant.
    Et je croyais aussi que l'interface graphique était dans un thread à  part.
  • AliGatorAliGator Membre, Modérateur
    novembre 2009 modifié #4
    Non, au contraire, tu dois toujours faire tout ce qui est relatif à  ton interface graphique (en particulier la mise à  jour de l'affichage) dans le thread principal.

    Va donc faire un tour dans la doc Apple, toujours aussi complète :
    Multi-Threading Programming Guide

    (Et si tu n'est pas obligé d'utiliser des Threads du moment que tu fais les choses de manière concurrencielles (parallélisées), il y a des alternatives à  l'utilisation des Threads, qui ont souvent des avantages pour te faciliter la vie (Grand Central Dispatch sous OSX.6, NSOperation & NSOperationQueues : Concurrency Programming Guide.)
  • NseaProtectorNseaProtector Membre
    21:55 modifié #5
    "En temps normal, j'ai un Thread qui régulièrement vient regarder la valeur d'un NSSlider"
    C'est bizarre de faire cela, non ?
    La logique cocoa serait plutôt que le slider update la valeur quand celle-ci a changé. Dans IB, tu peux cocher continue pour que l'action se fasse en continue et non au relâchement du slider.
  • GreensourceGreensource Membre
    21:55 modifié #6
    Oui oui c'est pas du tout à  faire "en vrai" on est d'accord. C'est ce que j'expliquais, en TP (je suis encore étudiant pour quelques mois ^^) on dois en gros reproduire une interface "à  événements" par nous même. C'est pour nous apprendre les Design Pattern habituellement mis en place pour ce genre de choses.
  • ClicCoolClicCool Membre
    21:55 modifié #7
    Dans l'optique d'une gestion d'évènements système ou tu implémentes tes propres handlers y'a p'tet cette possibilité ? (dans la doc qu'Ali a citée plus haut)
    Concurrency Programming Guide: Dispatch Sources: Writing and Installing an Event Handler
  • AliGatorAliGator Membre, Modérateur
    21:55 modifié #8
    Si c'est le design pattern de gestion des événements que tu dois utiliser, c'est pas tant un thread qui vient lire la valeur du slider tout le temps qu'il faut, c'est plutôt le slider qui doit poster un événement dans la pile d'événements quand sa valeur change, et une boucle (à  l'image d'une NSRunLoop) qui vient régulièrement dépiler ces événements pour les traiter. En tout cas c'est comme ça que je le mimerais.

    Donc en gros un [tt]NSMutableArray* eventsStack[/tt], quand ton slider change de valeur, un ajout d'un événement "ValueChanged" à  ce NSMutableArray, et dans ta RunLoop (par exemple en mettant en place un NSTimer qui va exécuter la méthode de traitement des événéments toutes les N millisecondes) tu dépiles les événements qu'il y a dans eventsStack pour les traiter un par un et exécuter la méthode associée à  chaque type d'événement.
    Tu peux à  la limite plutôt faire un thread qui va dépiler ces événements régulièrement, plutôt que scheduler une méthode sur la runloop de ton thread principal, mais si tu fais ça pense à  mettre des mutex via @synchronized(...) sur ton tableau eventStack puisque dans ce cas tu risques d'y accéder à  la fois en lecture (et dépilage) depuis ton thread secondaire et écriture (et empilage) depuis ton thread principal (qd le slider poste ses événements)...

    Mais au final, c'est de toute façon un peu zarb comme façon de faire :P
  • GreensourceGreensource Membre
    21:55 modifié #9
    En fait on a déjà  mis au point les pattern à  utilise en TD, donc je vais devoir les réutiliser. Mais bon après si j'avais le temps en effet ta solution est bien plus complète Ali.
    Mais là  on a trop de truc sur les bras  :o
Connectez-vous ou Inscrivez-vous pour répondre.