I tweeté plus tôt comme une blague, Mais c'est en fait une chose très sérieuse. J'ai eu plusieurs emplois dans la dernière année où j'ai été invité à examiner et proposer une ou des corrections réellement corriger les applications iPhone écrites par d'autres développeurs. Une chose que j'ai vu à plusieurs reprises dans le code que j'ai examinés est quelque chose comme cela jonché toute l'application:
Ce code provoque le thread ça s'appelle du rien faire pour la durée de temps spécifiée. Alors, je vais regarder dans le code pour quelque indication que la demande est filetages de frai. Jusqu'ici, dans tous les cas, l'application n'avait pas engendré aucun fils, explicitement ou implicitement en utilisant NSOperationQueue. Si vous n'avez pas détachée des threads, et vous appelez sleepForTimeInterval:, vous dormez thread principal de l'application, et c'est une très mauvaise chose à faire.
Habituellement, je vois ces sleepForTimeInterval: appels dans les applications qui faire une sorte de réseau de communication asynchrones. Ma conjecture est que les développeurs qui ont écrit ces demandes provenaient de Java,. Net, ou une autre langue, où la communication réseau est communément traitées sur un fil non principale. Dans ces langues, il n'est pas rare de voir le code qui met le thread de travail du réseau en veille ou en une boucle pour faire attendre une réponse et de tenir compte de tout décalage potentiel. Ce n'est pas une bonne approche, mais dans ces environnements, il fonctionne en général.
In Touch Cacao et, cependant, à moins que vous frayer un fil et d'enregistrer vos communications réseau avec boucle exécuter le thread généré, votre réseau de communication utilisant CFNetwork ainsi que toute mise en réseau fait en utilisant la fonctionnalité intégrée de réseau qui existe dans les classes Cocoa nombreuses tout se passe sur le thread principal.
Un autre problème lié que je vois parfois quelque chose comme ceci:
Ce code a quelques choses vraiment mauvais passe. Il est important de garder à l'esprit que les méthodes IBAction toujours le feu sur le thread principal. Ainsi, le premier problème est l'appel à dataWithContentsOfURL:. C'est ce qu'on appelle un bloquer le fonctionnement du réseau, Ce qui signifie que d'appeler cette méthode permettra d'éviter tout autre code sur ce fil de s'exécuter jusqu'à ce que toutes les données ont été reçues, car la méthode ne sera pas de retour jusqu'à ce que ce qui s'est passé. La même chose est vraie pour tous les constructeurs de commodité qui contiennent withContentsOfURL: en leur nom. Alors que vous pouvez probablement vous en sortir avec une utilisation très limitée de ces méthodes pour très petits morceaux de données, vous devriez vraiment être en utilisant uniquement les appels du réseau asynchrone dans vos applications. Vous ne pouvez pas prédire combien de temps les communications réseau se tiendra, même avec de petits morceaux de données. Si les radios sont éteints, les connexions EDGE peut prendre plusieurs secondes pour rétablir, ce qui est assez long pour que vos utilisateurs remarqueront probablement le gel.
Le deuxième problème avec ce fil est la boucle while. Petites boucles sont souvent correct dans les méthodes d'action, mais ceux qui pourraient potentiellement être grande ou lorsque la longueur de la boucle est tout simplement impossible de savoir (qui est généralement le cas avec tout (1) ou while (TRUE) boucles), vous n ' t voulez faire le traitement sur le thread principal.
Si vous dormez le thread principal, littéralement rien ne peut arriver dans votre application sauf pour l'exécution du thread d'arrière-plan. Si vous n'avez pas donné naissance à toute les discussions de fond, alors rien ne peut arriver à peu près tout. Votre interface utilisateur se bloque et votre utilisateur ne sera pas en mesure d'utiliser l'application. Boutons sera pas mis en évidence quand on tape dessus et animations se fige en place. Mais c'est encore pire que le gel d'interface (qui est certainement assez mauvaise), tout le traitement des événements et réseau de communication se bloque également. Tout ce qui est manipulé par la boucle de votre application principale manifestation n'a tout simplement pas se produire alors que le thread principal est endormi.
Je n'ai pas encore vu une situation où l'appel sleepForTimeInterval: sur le thread principal est une bonne idée.
Si vous effectuez une opération de longue haleine sur le thread principal, votre code va monopoliser le thread principal et le résultat final sera essentiellement le même que le sommeil le thread principal pendant que votre boucle. Aucune interaction utilisateur, aucun réseau de communication, pas d'animation.
Si vous voulez une bonne introduction sur la façon d'avoir des trucs hors de votre thread principal, consultez Blog de Dave Dribbin sur des opérations simultanées. Plus l'iPhone 3 de développement consacre également un chapitre complet à différents types de concurrence.
[NSThreadsleepForTimeInterval:0.3];Ce code provoque le thread ça s'appelle du rien faire pour la durée de temps spécifiée. Alors, je vais regarder dans le code pour quelque indication que la demande est filetages de frai. Jusqu'ici, dans tous les cas, l'application n'avait pas engendré aucun fils, explicitement ou implicitement en utilisant NSOperationQueue. Si vous n'avez pas détachée des threads, et vous appelez sleepForTimeInterval:, vous dormez thread principal de l'application, et c'est une très mauvaise chose à faire.
Habituellement, je vois ces sleepForTimeInterval: appels dans les applications qui faire une sorte de réseau de communication asynchrones. Ma conjecture est que les développeurs qui ont écrit ces demandes provenaient de Java,. Net, ou une autre langue, où la communication réseau est communément traitées sur un fil non principale. Dans ces langues, il n'est pas rare de voir le code qui met le thread de travail du réseau en veille ou en une boucle pour faire attendre une réponse et de tenir compte de tout décalage potentiel. Ce n'est pas une bonne approche, mais dans ces environnements, il fonctionne en général.
In Touch Cacao et, cependant, à moins que vous frayer un fil et d'enregistrer vos communications réseau avec boucle exécuter le thread généré, votre réseau de communication utilisant CFNetwork ainsi que toute mise en réseau fait en utilisant la fonctionnalité intégrée de réseau qui existe dans les classes Cocoa nombreuses tout se passe sur le thread principal.
Un autre problème lié que je vois parfois quelque chose comme ceci:
- (IBAction)soSomething
{
NSData *data = [NSDatadataWithContentsOfURL:[NSURLurlWithString:@"http://foo.com/reallybigdatafile"]];
while(1)
{
// parse really big data file and break when done
}
}Ce code a quelques choses vraiment mauvais passe. Il est important de garder à l'esprit que les méthodes IBAction toujours le feu sur le thread principal. Ainsi, le premier problème est l'appel à dataWithContentsOfURL:. C'est ce qu'on appelle un bloquer le fonctionnement du réseau, Ce qui signifie que d'appeler cette méthode permettra d'éviter tout autre code sur ce fil de s'exécuter jusqu'à ce que toutes les données ont été reçues, car la méthode ne sera pas de retour jusqu'à ce que ce qui s'est passé. La même chose est vraie pour tous les constructeurs de commodité qui contiennent withContentsOfURL: en leur nom. Alors que vous pouvez probablement vous en sortir avec une utilisation très limitée de ces méthodes pour très petits morceaux de données, vous devriez vraiment être en utilisant uniquement les appels du réseau asynchrone dans vos applications. Vous ne pouvez pas prédire combien de temps les communications réseau se tiendra, même avec de petits morceaux de données. Si les radios sont éteints, les connexions EDGE peut prendre plusieurs secondes pour rétablir, ce qui est assez long pour que vos utilisateurs remarqueront probablement le gel.
Le deuxième problème avec ce fil est la boucle while. Petites boucles sont souvent correct dans les méthodes d'action, mais ceux qui pourraient potentiellement être grande ou lorsque la longueur de la boucle est tout simplement impossible de savoir (qui est généralement le cas avec tout (1) ou while (TRUE) boucles), vous n ' t voulez faire le traitement sur le thread principal.
Pourquoi Tout ceci est mauvais
Si vous dormez le thread principal, littéralement rien ne peut arriver dans votre application sauf pour l'exécution du thread d'arrière-plan. Si vous n'avez pas donné naissance à toute les discussions de fond, alors rien ne peut arriver à peu près tout. Votre interface utilisateur se bloque et votre utilisateur ne sera pas en mesure d'utiliser l'application. Boutons sera pas mis en évidence quand on tape dessus et animations se fige en place. Mais c'est encore pire que le gel d'interface (qui est certainement assez mauvaise), tout le traitement des événements et réseau de communication se bloque également. Tout ce qui est manipulé par la boucle de votre application principale manifestation n'a tout simplement pas se produire alors que le thread principal est endormi.
Je n'ai pas encore vu une situation où l'appel sleepForTimeInterval: sur le thread principal est une bonne idée.
Si vous effectuez une opération de longue haleine sur le thread principal, votre code va monopoliser le thread principal et le résultat final sera essentiellement le même que le sommeil le thread principal pendant que votre boucle. Aucune interaction utilisateur, aucun réseau de communication, pas d'animation.
Si vous voulez une bonne introduction sur la façon d'avoir des trucs hors de votre thread principal, consultez Blog de Dave Dribbin sur des opérations simultanées. Plus l'iPhone 3 de développement consacre également un chapitre complet à différents types de concurrence.
Aucun commentaire:
Enregistrer un commentaire