Grand Central Dispatch ?
NseaProtector
Membre
Bonsoir,
Si j'ai bien compris désormais sous Léo, nous devrions remplacer les threads par ce que propose la nouvelle API "Grand central Dispatch".
Par quoi je remplace mon thread ? Une simple indication pour que je me lance a essayer ça ?
Je vous joint le code que je compte adapter :
Si j'ai bien compris désormais sous Léo, nous devrions remplacer les threads par ce que propose la nouvelle API "Grand central Dispatch".
Par quoi je remplace mon thread ? Une simple indication pour que je me lance a essayer ça ?
Je vous joint le code que je compte adapter :
@implementation AppController<br /><br />- (id)init<br />{<br /> self = [super init];<br /> if (self) <br /> {<br /> // Mise en place de valeur par defaut<br /> intervalTempo = 1250; // ecart pour 120BPM et 25 pas à la noire.<br /> isRunning = TRUE;<br />//Timer qui update l'interface<br /> bpmTimer = [[NSTimer scheduledTimerWithTimeInterval:0.4<br /> target:self<br /> selector:@selector(pulseBpm:)<br /> userInfo:nil<br /> repeats:YES] retain];<br /> NSLog(@"playNextCue: timer started");<br />//Thread qui incrémente "mon horloge" en arrière plan<br /> [NSThread detachNewThreadSelector:@selector(tempoClock:)toTarget:self withObject:[bpmText stringValue]];<br /> NSLog(@"Thread started");<br /> return 0 ;<br /> }<br />}<br />- (void) pulseBpm:(NSTimer*)aTimer<br />{<br />// NSLog(@"Horloge: %f",clockTempo);<br />//horloge est un NSTextField, clockTempo un float<br /> [horloge setFloatValue:clockTempo];<br /> }<br />//-----------------------------------------------------------<br />// SECTION DES THREADS<br />//-----------------------------------------------------------<br />#pragma mark -<br />#pragma mark Threads <br />-(void)tempoClock:(NSString *)directoryName<br />{<br /> NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];<br /> // boucle while<br /> // tant que la condition n'est pas remplie, on incrémente l'horloge<br /> while (isRunning == TRUE)<br /> {<br /> clockTempo++;<br /> usleep(intervalTempo);<br /> }<br /> [pool release];<br /> <br />}
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Et ce n'est pas une obligation, les threads continuent à fonctionner, hein...
Il y a plein d'articles intéressants sur GCD et les blocks sur NSBlog:
Mais en gros, ca devrait ressembler à ça :
à la place de la ligne qui démarre le thread.
Mais attention, à partir du moment ou GCD (ou même uniquement les blocks) est utilisé, l'application ne peut fonctionner que sous Snow Leopard. Adieu la compatibilité avec Leopard et précédents...
Oui, c'est ce que j'allais dire, ce n'est pas une obligation d'utiliser GCD à la place des threads, les threads existeront toujours. Après, en effet si tu as l'occasion d'essayer GCD, c'est une bonne chose que d'essayer de t'y mettre... Mais...
En fait, GCD est basé sur des "tâches" que l'on veut exécuter de manière asynchrone. On lui passe une fonction, ou un "Block" (code encapsulé dans un objet, en quelques sortes), et on lui laisse l'exécuter quand il aura le temps. Avec des fonctions propres à GCD qui permettent de synchroniser les appels à bouts de code qu'une fois que l'autre bout de code est fini, etc...
Là j'avoue que sur ton code, j'ai du mal à voir ce qu'il fait, mais aussi l'intérêt d'utiliser un thread ici alors que tu pourrais t'en passer à priori si j'ai bien compris ton code... et en plus tu n'as rien protégé !
Alors d'une, si tu gardais les threads, il faudrait protéger tes variables. Là tu as une variable "clockTempo" qui est accédée à la fois par ton thread principal dans pulseBpm, et dans ton thread tempoClock, et tu n'as mis aucun mutex pour protéger l'accès concurrent entre les threads.
D'autre part, pourquoi utiliser un thread ici, dont finalement le rôle revient à compter le nombre de fois que tu as passé intervalTempo microsecondes, alors qu'il y a des solutions plus simples et moins "dangereuses" ?
Car en gros si j'ai bien compris tu as un truc que tu peux mettre en lecture et en pause et tu veux savoir où tu en es de ta lecture, c'est ça ?
Donc déjà , plutôt que ton thread, tu pourrais utiliser simplement un NSTimer qui se déclenche toutes les intervalTempo, non ? en mode repeat:YES ? Ca ne suffirait pas ?
Et sinon tu peux faire un truc ressemblant à ça, dans l'idée : Avec ça, quand tu veux démarrer ta lecture depuis zéro, tu fais [self resetClockTempo] pour remettre ton compteur à zéro, puis un [self setRunning:YES] pour démarrer.
Ensuite, si tu veux mettre en pause, tu fais [self setRunning:NO] pour mémoriser le cumul de temps écoulé jusque là , et comme ça quand tu veux enlèver ta pause, tu refais un [self setRunning:YES], ça va reprendre comme date de référence la date actuelle (donc tes différences entre lastStartDate et Now seront OK), mais grace à cumulTempo tu n'auras pas perdu les secondes et millisecondes déjà accumulées avant ta pause...
Après, tu peux faire ça sous cette forme, ou avec un NSTimer, mais utiliser un NSThread pour ça, c'est un peu violent :P
Et en plus, je suis même pas sûr que pour ton cas, ou ton thread boucle, l'utilisation de GCD t'apporte qqch, car il est plus orienté exécutions de tâches (un peu comme NSOperation), moins pour un thread qui tourne en tâche de fond en continu.
En effet cela ne semble pas si compliqué GCD... (à vérifier en pratique)
Pour clarifier les interrogations d'Ali :
C'est un bout de code d'essais en vue de réaliser un séquenceur DMX. L'idée c'est que le thread ou les threads devront sans être gelé envoyer des boucles de valeurs en tâche de fond et cadencé selon le rythme. (Je ne suis pas sur de l'organisation exact encore ...)
Quand a l'utilisation de GCD, c'est juste une curiosité et je me demandais si dans mon cas cela ne pouvait pas simplifier ou apporter quelque chose .
Par exemple, imagine que tu as une tableView, et que quand tu cliques sur un bouton, ça va faire tout plein de calculs qui vont remplir un NSArray de valeurs longues à calculer, et que tu vas ensuite afficher dans ton tableView.
Si tu fais ça d'une traite : Si tu codes ça comme ça, et si computeData prend beaucoup de temps, ton application va bloquer (risque de roue multicolore au passage) pendant que computeData fera sa tambouille...
Dans ce genre de cas, GCD te permet de dire "bon, déporte le calcul de computeData dans un thread séparé, tu fais cette tâche en tâche de fond, et quand tu as fini, tu mets à jour la tableView. Ce qui donne la modification suivante :
Parcontre si en dehors du thread je ne fait que lire la variable, tu penses que je dois la protéger quand même ?
(Et mêmeque ça serait plus simple d'utiliser un timer, qui utilise la RunLoop de ton mainThread pour se déclencher et non un thread séparé, donc moins de risques si tu ne maà®trises pas les threads d'avoir des pb comme des deadlocks ou des variables non protégées et des crash...)
Ok, Merci encore. Les timers dans la RunLoop, ça va geler mon séquenceur des que je vais appuyer sur un bouton ou agrandir ma fenêtre par exemple.
Sur cette autre discussion il est dit que les NSOperation utilisait automatiquement GCD si le système sur lequel est lancé l'application dispose de GCD. J'aurais voulu quelques précisions parce que je suis justement entrain de lire la documentation d'Apple sur GCD et la programmation parallèle et pourtant je ne trouve aucun endroit ou il est dit que GCD est utilisé pas les NSOperation.
Ce que je comprend dans la Doc, c'est que si je veux utiliser GCD je dois faire un block et l'ajouter dans une "dispatch queue".
Pourtant ça semble en effet logique que NSOperation utilise GCD, d'autant qu'Apple en faisant la promo de GCD disait que juste en re-compilant une application multi-threadé cela permettait d'augmenter la performance d'une appli. Ce qui laisse supposer la modification des API existantes (NSOperation?) pour qu'elles utilisent désormais GCD. J'aimerais juste savoir si quelqu'un sait ou trouver cette information?
Merci