2016-05-31 3 views
1

Dans l'objectif C, je fais mon programme à attendre en utilisant en boucleUtilisation de while (true) une approche valide dans la programmation iOS?

fonction
doInitialize() 
{ 
dispach_group_t loadDataGroup=dispatch_group_create(); 
dispatch_group_async(loadDataGroup,...get_global_queue(..),0),^{ 
    renewauth(); 
} 
dispatch_group_notify(loadDataGroup,...get_global_queue(..),0),^{ 
    //Do other tasks once renew session has completed... 
} 
} 
renewauth() 
{ 
RenewAuthTokenInProgress=true; 
startRenewThread(); 
**while (RenewAuthTokenInProgress);** 
} 

À son tour startRenewThread() effectue également dispatch_async opération à l'intérieur. Donc je dois attendre renewAuth().

Et tâche Async startRenewThread mettra à jour la variable bool une fois le renouvellement est réussi.

Y at-il une meilleure approche de le faire autre que dispatch_groups? Et est-il bon que les autres threads attendent avec while (true)?

+0

L'attente occupée est une idée terrible. Pourquoi exécutez-vous cette fonction de renouvellement en arrière-plan si vous voulez bloquer jusqu'à ce que ce soit fait de toute façon? – Thilo

+0

Et si vous allez sur la route asynchrone, qu'est-ce qui ne va pas avec 'dispatch_groups'? – Thilo

+1

En supposant que RenewAuthTokenInProgress reste vrai pendant un certain temps, alors oui votre iPhone va devenir chaud. Vous allez exécuter l'un des cœurs à 100%. Cela va aussi aplatir votre batterie. – TJA

Répondre

6

Manoj Kumar,

en utilisant une boucle while attendre jusqu'à ce que le changement de variable booléenne n'est pas la bonne approche pour résoudre le problème. Voici quelques-uns des problèmes avec cette méthode

  1. Votre CPU est obligé de vérifier régulièrement la variable.

  2. Cela montrera clairement que le développeur est pas beaucoup equipted avec des compétences de base de codage et les fonctionnalités disponibles avec le langage.

  3. Si pour une raison quelconque votre variable ne changera jamais, votre CPU ne cessera jamais de vérifier la valeur de bool in while loop et bloque l'exécution de code supplémentaire sur le même thread.

Voici quelques-unes de l'approche correcte:

  1. blocs ou fermetures: Exploitez les blocs pour exécuter le code de manière asynchrone lorsque le RenewAuthToken est fait. Délégués: si les blocs sont plus difficiles à comprendre, utilisez les délégués et déclenchez le délégué lorsque vous avez terminé avec RenewAuthToken. Notifications: Ajouter un observateur pour les notifications dans les classes qui doit répondre lorsque RenewAuthToken est fait et lancer une notification de l'asynctask et laisser la classe pour l'attraper exécuter le code.

  2. Locks: S'il est nécessaire de bloquer l'exécution du fil jusqu'à ce que la réponse se verrouille utiliser pour contrôler l'exécution du thread plutôt que d'utiliser while

EDIT

Comme l'a par fogmeister dans les commentaires

Si vous bloquez le thread principal pendant trop longtemps avec une boucle while (true) alors l'application sera effectivement mis fin par le chien de garde iOS car il supposer qu'il est tombé en panne

S'il vous plaît consulter le lien: understand iOS watchdog termination reasons fourni par fogmeister

Hope it helps.

+3

Aussi quelque chose à noter. Si vous bloquez le thread principal trop longtemps avec une boucle while (true), l'application sera automatiquement arrêtée par iOS Watchdog car elle supposera qu'elle s'est écrasée. – Fogmeister

+0

@fogmeister: Bingo :) up vote pour cela :) –

+1

Un lien pour vous d'ajouter si vous voulez https://developer.apple.com/library/ios/technotes/tn2151/_index.html une recherche de '8badf00d' montrera les raisons de terminaison de chien de garde. – Fogmeister

1

Je crois que ce que vous avez besoin est un semaphore comme:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ 

dispatch_semaphore_t sem = dispatch_semaphore_create(0); 
__block BOOL done = FALSE; 
while (true) { 

    [self someCompletionMethod completion:^(BOOL success) { 

     if(success) { // Stop condition 
      done = TRUE; 
     } 
     // do something 
     dispatch_semaphore_signal(sem); // This will let a new iteration 
    }]; 

    dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); 

    if(done) { 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      // Dispatch to main 
      NSLog(@"Done!"); 
      break; 
     }); 
    } 
} 

}); 

sémaphores sont un concept de thread old-school introduit dans le monde par le toujours aussi humble Edsger Dijkstra. Les sémaphores sont un sujet complexe car ils s'appuient sur les subtilités des fonctions du système d'exploitation.

Vous pouvez voir un tutoriel ici de sémaphores et vérifier plus de liens: https://www.raywenderlich.com/63338/grand-central-dispatch-in-depth-part-2

J'espère que cela peut vous aider.

+0

Pas d'infraction, mais les sémaphores sont souvent un alibi pour la paresse de ne pas traiter la gestion des modèles asynchrones. – vadian

+1

Pas d'infraction, mais les sémaphores sont souvent une belle façon de gérer les événements asynchrones. Pour cette question particulière, le plus probable n'est pas le bon choix. Et une technique avancée, probablement au-delà de l'OP. – gnasher729

+0

Il n'y a aucune infraction, Merci pour les deux commentaires, je crois que c'est tout à fait d'opinion et je suis d'accord avec gnasher729 mais j'ai vraiment compris ce que vous voulez dire vadian. –

0

Ce que vous faites est absolument mortel. Il bloque le thread en cours d'exécution (vraisemblablement le thread principal) de sorte que l'interface utilisateur est gelée. Il fonctionne sur un noyau à 100% de charge sans aucune raison ce qui vide la batterie rapidement et réchauffe le téléphone. Cela vous amènera des clients très, très mécontents ou très, très heureux ex-clients. Tout ce qui suit doit être exécuté en arrière-plan: startRenewThread doit déclencher une action qui définit RenewAuthTokenInProgress = NO et définit s'il y a un nouveau jeton ou non, puis déclenche une autre action.

Ceci est un modèle de programmation absolument essentiel sur iOS (et Android pour autant que je sache).