Affichage et calculs dans deux threads différents
iSofTom
Membre
Bonjour,
Je suis en train de faire une application et je me posais une question:
Pour que l'affichage soit toujours fluide et non fonction du temps que prend les calculs, j'utilise deux threads.
J'ai testé et ça a l'air de marcher, mais est-ce la bonne méthode?
Est-ce qu'il y a autre chose de mieux à faire?
merci.
Je suis en train de faire une application et je me posais une question:
Pour que l'affichage soit toujours fluide et non fonction du temps que prend les calculs, j'utilise deux threads.
- Mon thread principal ne fait rien (en tout cas de lui-même)
- Mon deuxième thread fait des calculs, et quand une vue change il appel la méthode setNeedsDisplay sur le thread principal qui va donc se charger de réafficher.
J'ai testé et ça a l'air de marcher, mais est-ce la bonne méthode?
Est-ce qu'il y a autre chose de mieux à faire?
merci.
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Faut juste faire attention quand tu as plusieurs threads à ce que tes accès à tes variables partagées entre tes deux threads (comme la variable contenant le résultat de ton calcul, écrite par le thread qui fait le calcul et lue par le thread principal qui l'affiche) soient bien protégés (donc s'assurer d'y accéder via une @property qui ne soit pas déclarée en nonatomic, ou alors mettre des @synchronized(self) autour des accès de cette variable, etc)
Une autre question dans ce cas:
pourquoi l'affichage devrait-il toujours être dans le thread principal? N'est-ce pas possible de faire les calculs dans le principal et l'affichage dans un secondaire ? (c'est juste par curiosité)
Au final, quand tu demandes de dessiner qqch à l'écran ou changer le texte d'un UILabel, etc... ça ne va pas le dessiner directement et immédiatement à l'écran. Ca va mémoriser l'événement de dessin, dessiner dans un buffer... et c'est seulement à la prochaine boucle de rafraà®chissement de l'écran que ce buffer sera effectivement sur ton écran. Seule la RunLoop du MainThread effectue cette gestion de l'affichage.
Et heureusement sinon ça serait le bordel de devoir mettre des mutex de partout à chaque opération de dessin pour éviter que deux threads écrivent en même temps dans le buffer de la carte vidéo !!
[EDIT] Lien vers la doc Apple pour plus d'infos sur le cycle de vie d'une application
Merci pour ta réponse...
En fait, on a affaire ici à l'un des points les plus obscures d'OSX.
Pour Apple l'AppKit est thread safe sauf exception.
L'avis des devs sur le web c'est plutôt: l'appKit n'est pas thread safe sauf exception.
Naturellement les choses évoluent à chaque révision de l'OS.
En plus là on est sur l'iPhone.
Il se peut même que tout ce que je viens de dire n'a aucun sens.
Va savoir
- Threads and your User interface
- Application Kit Framework Thread Safety
C'est valable sur l'iphone et sur le mac et c'est plutôt clair: Il y a des classes thread safe et d'autres non thread safe dans l'appKit et dans foundation. Donc surtout ne pas généraliser voir ici : (http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/Multithreading/ThreadSafetySummary/ThreadSafetySummary.html
Le multithreading est vraiment un truc compliqué à ne pas utiliser à la légère. Ca peu marcher et puis t'exploser à la tronche sans prévenir. Il y a des alternatives (idle notification ou run loop observers). Et si vraiment t'as pas le choix, une approche fire&forget est préferable à l'usage de lock. Dans ton cas par exemple lorsque les calculs sont finis, tu balances un performSelectorOnMainThread avec tes résultats et tu utilises un nouvel objet dans le thread de calcul. Comme ça à tout moment seul un unique thread utilise la donnée et tout ça sans lock.
Manu