Lancer un thread et l'arrêter...

orfaitorfait Membre
22:37 modifié dans API AppKit #1
Bonjour,

Je viens demander un coup de main (un coup de clavier?) pour une histoire de thread.
Avant de rentrer dans le vif du sujet, j'explique mon problème d'origine.
Je commande une interface USB en lui envoyant des données toutes les 20ms. Si les données à  envoyer sont inchangées, on zappe l'envoi pour éviter de saturer l'interface.

J'ai donc créé un logiciel. Pour simplifier l'explication, on va dire que ce logiciel n'a qu'un seul slider et une seule checkbox. Le but est d'envoyer la valeur du slider avec le rafraà®chissement prévu quand la case est cochée.

Mon idée de départ :
Lorsqu'on coche la case, on lance un timer qui se répète et exécute toutes les 20ms un code pour l'envoi des données.
Quand on décoche, on invalide le timer.
Le slider est paramétré pour envoyer de façon continue sa valeur lors de son déplacement.
Tout semble fonctionner dans un premier temps mais en y regardant de plus près, on remarque que pendant le déplacement du slider, le timer est en "pause", donc pour que la valeur passe, il faut relâcher le clic de souris.
>> Il faut donc rendre l'envoi des données "indépendant".

Mon idée a donc été de me tourner vers le multithread.

La nouvelle idée, celle que je vous demande de commenter :
Lorsqu'on coche la case, on met une variable secuthread à  1 et on lance un thread :
- (void)Refresh<br />{<br />[NSThread detachNewThreadSelector:@selector(senddata:)<br />toTarget:self<br />withObject:nil];<br />}<br /><br />- (void) senddata:(id)object<br />{<br />NSAutoreleasePool * localPool = [[NSAutoreleasePool alloc] init];<br />while (1)<br />{<br />//Traitement et envoi des données<br />envoiusb(valeur_slider);<br />}<br />sleep(0.2);<br />if (secuthread == 0x0) break;<br />}<br />[localPool release];<br />}


Et l'action associée au slider met à  jour la variable valeur_slider.

Si on décoche, on met secuthread à  0 et hop, le thread semble se terminer.
Si je teste avec ObjectAlloc : dans NSThread, la valeur de current revient bien à  1.
Conclusion personnelle : ça fonctionne.
Question personnelle : et le priorités sur la variables ? Normalement, avec la fonction sleep, on ne doit pas avoir de deadlock.
Remarque personnelle : merci de ne pas me frapper pour le while(1)... je viens du monde de la prog de microcontrôleur et la chose est courante.



Voilà , dà®tes moi ce que vous en pensez...
Merci
Albin

Réponses

  • schlumschlum Membre
    22:37 modifié #2
    Oui, c'est pas mal... Quelques remarques :

    1 - Pourquoi ne pas faire :
    do {<br />&nbsp; &nbsp; // ...<br />} while([myCheckBox state]==1);
    

    ?

    2 - Avec ce système de "sleep", ça ne sera pas exécuté toutes les 20ms exactement (mais c'est peut-être pas dramatique...)
  • MalaMala Membre, Modérateur
    22:37 modifié #3
    Je dirais même plus...
    <br />do <br />{<br />&nbsp; &nbsp; NSAutoreleasePool * secondaryPool = [[NSAutoreleasePool alloc] init];<br /><br />&nbsp; &nbsp; // ...<br /><br />&nbsp; &nbsp; [secondaryPool release];<br />} while([myCheckBox state]==1);<br />
    


    Comme ça, si ta boucle tourne longtemps, ça va éviter de faire monter la mémoire si il y a des données Autorelease dans la boucle de traitement.

    Pour ton slider, tu as bien coché l'option "Continuously send action while sliding"?
  • orfaitorfait Membre
    juillet 2007 modifié #4
    Alors dans l'ordre :

    while([myCheckBox state]==1) : bonne idée, ça fonctionne et c'est tout bête  :P

    Pour le "sleep", c'est bon, la précision n'est pas importante.

    Et j'ai suivi ton conseil Mala et "Continuously send action while sliding" était bien coché dès le dépard (et pour répondre à  ton mail, oui, j'ai utilisé un NSTimer donc pb avec MainThread comme tu dis).


    Après test, j'ai remarqué que ça prend 70% de processeur cette boucle... un peu trop je trouve.
    Il y a moyen de corriger ça ?
  • schlumschlum Membre
    22:37 modifié #5
    dans 1184270310:

    Après test, j'ai remarqué que ça prend 70% de processeur cette boucle... un peu trop je trouve.
    Il y a moyen de corriger ça ?


    C'est là  que c'est le moment d'utiliser Shark pour voir ce qui bouffe le processeur  ;)
  • orfaitorfait Membre
    22:37 modifié #6
    Shark me répond ceci (pour ce qui bouffe, j'ai zappé le reste) :
    # Report 1 - Session 1 - Time Profile of VideoScan<br />SharkProfileViewer<br /># Generated from the visible portion of the outline view<br />+ 40.2% ml_set_interrupts_enabled (mach_kernel)<br />| + 30.4% thread_block_reason (mach_kernel)<br />| | + 30.4% thread_block (mach_kernel)<br />| | | + 30.2% mach_wait_until_trap (mach_kernel)<br />| | | |&nbsp;  30.2% find_user_regs (mach_kernel)<br />| | | + 0.1% ipc_mqueue_receive (mach_kernel)<br />| | | | + 0.1% mach_msg_overwrite_trap (mach_kernel)<br />| | | | |&nbsp;  0.1% find_user_regs (mach_kernel)<br />| | | + 0.0% mach_msg_overwrite_trap (mach_kernel)<br />| | | |&nbsp;  0.0% find_user_regs (mach_kernel)<br />| - 8.6% assert_wait_deadline (mach_kernel)<br />| - 0.4% thread_invoke (mach_kernel)<br />| - 0.4% cache_flush_page_phys (mach_kernel)<br />|&nbsp;  0.1% find_user_regs (mach_kernel)<br />| - 0.1% pmap_enter (mach_kernel)<br />| - 0.0% lo_mach_scall (mach_kernel)<br />| - 0.0% chudxnu_cpu_free (mach_kernel)<br />| - 0.0% pmap_expand (mach_kernel)<br />| - 0.0% fpnoextflt (mach_kernel)<br />| - 0.0% ast_taken (mach_kernel)<br />+ 12.2% -[VideoScanControler senddata:] (VideoScanControler.ob)<br />| + 11.6% forkThreadForFunction (Foundation)<br />| |&nbsp;  11.6% _pthread_body (libSystem.B.dylib)<br />| - 0.5% 0x3982df [2.2KB] (Unknown Library)<br />| - 0.1% 0xffffffff8ac199da [unreadable] (Unknown Library)<br />| - 0.0% 0xffff87c0 [unknown] (Unknown Library)<br />| - 0.0% 0x35182f [3.1KB] (Unknown Library)<br />- 11.7% nanosleep (libSystem.B.dylib)
    


    Après, pour l'interprétation... je veux bien. Mais la résolution là  je dois apprendre  :why?:

    EDIT : VideoScan, c'est le nom de l'appli mais ce n'est ni une camera video, ni un scanner...
  • schlumschlum Membre
    22:37 modifié #7
    http://lists.apple.com/archives/PerfOptimization-dev/2007/May/msg00032.html

    Une grosse partie se passe dans le noyau... Pas très clair.
  • orfaitorfait Membre
    juillet 2007 modifié #8
    Résolu après reboot ?

    Je vais tenter, je vous tiens au courant.

    EDIT : j'ai tenté, aucun changement.
  • orfaitorfait Membre
    22:37 modifié #9
    J'ai trouvé par chance à  vrai dire.
    j'avais écrit : sleep(0.02).
    Si on regarde juste avant, il y a : - 11.7% nanosleep (libSystem.B.dylib)
    Hors, nanosleep est appelé par nsleep (de mémoire). Donc ca veut dire nsleep(20 000 000) !!
    En corrigeant par usleep(20 000), la consommation cpu chute à  3%.

    Elle est pas belle la vie ?
  • schlumschlum Membre
    22:37 modifié #10
    Ah oui, j'avais pas remarqué...

    "sleep" prend un "int" !
    Donc pour lui, 0.02 = 0 -> aucune attente, le processeur n'avait aucun repos...

    Donc c'était bien ça, mais pas pour la raison que tu pensais :P
Connectez-vous ou Inscrivez-vous pour répondre.