web-dev-qa-db-fra.com

Comprendre NSRunLoop

Quelqu'un peut-il expliquer ce qu'est NSRunLoop? Donc, comme je le sais, NSRunLoop est un élément lié à NSThread, n'est-ce pas? Donc, supposons que je crée un fil comme

NSThread* th=[[NSThread alloc] initWithTarget:self selector:@selector(someMethod) object:nil];
[th start];

-(void) someMethod
{
    NSLog(@"operation");
}

donc après que ce fil ait fini son travail, non? pourquoi utiliser RunLoops ou où l’utiliser? from Apple docs j'ai lu quelque chose, mais ce n'est pas clair pour moi, alors expliquez-le aussi simplement que possible

97
taffarel

Une boucle d’exécution est une abstraction qui (entre autres choses) fournit un mécanisme permettant de gérer les sources d’entrée du système (sockets, ports, fichiers, clavier, souris, minuteries, etc.).

Chaque NSThread a sa propre boucle d'exécution, accessible via la méthode currentRunLoop.

En général, il n'est pas nécessaire d'accéder directement à la boucle d'exécution, bien que certains composants (réseau) puissent vous permettre de spécifier la boucle d'exécution qu'ils utiliseront pour le traitement des E/S.

Une boucle d’exécution d’un thread donné attendra qu’une ou plusieurs de ses sources d’entrée aient des données ou des événements, puis déclenchera le ou les gestionnaires d’entrée appropriés pour traiter chaque source d’entrée "prête".

Après cela, il retournera à sa boucle, traitera les entrées de différentes sources et "dormira" s’il n’ya pas de travail à faire.

C'est une description assez détaillée (en essayant d'éviter trop de détails).

[~ # ~] éditer [~ # ~]

Une tentative pour répondre au commentaire. Je l'ai cassé en morceaux.

  • cela signifie que je ne peux accéder/exécuter que pour exécuter la boucle à l'intérieur du fil droit?

Effectivement. NSRunLoop n'est pas thread-safe et ne doit être accessible qu'à partir du contexte du thread qui exécute la boucle.

  • y at-il un exemple simple, comment ajouter un événement à exécuter en boucle?

Si vous souhaitez surveiller un port, vous devez simplement ajouter ce port à la boucle d'exécution, puis la boucle d'exécution surveillera l'activité de ce port.

- (void)addPort:(NSPort *)aPort forMode:(NSString *)mode

Vous pouvez également ajouter une minuterie explicitement avec

- (void)addTimer:(NSTimer *)aTimer forMode:(NSString *)mode
  • que veut-il ensuite retourner dans sa boucle?

La boucle d’exécution traitera tous les événements prêts à chaque itération (selon son mode). Vous devrez consulter la documentation pour en savoir plus sur les modes d'exécution, car cela dépasse un peu le cadre d'une réponse générale.

  • la boucle est-elle inactive quand je démarre le fil?

Dans la plupart des applications, la boucle d'exécution principale s'exécutera automatiquement. Cependant, vous êtes responsable du démarrage de la boucle d'exécution et de la réponse aux événements entrants pour les threads que vous créez.

  • est-il possible d'ajouter des événements à la boucle d'exécution du thread en dehors du thread?

Je ne suis pas sûr de ce que vous voulez dire ici. Vous n'ajoutez pas d'événements à la boucle d'exécution. Vous ajoutez des sources d'entrée et des sources de minuterie (à partir du thread qui possède la boucle d'exécution). La boucle d’exécution les surveille ensuite pour détecter toute activité. Vous pouvez bien sûr fournir des données à partir d'autres threads et processus, mais les entrées seront traitées par la boucle d'exécution qui surveille ces sources sur le thread qui exécute la boucle d'exécution.

  • est-ce que cela signifie que parfois je peux utiliser la boucle d'exécution pour bloquer le fil pendant un certain temps

Effectivement. En fait, une boucle d'exécution "restera" dans un gestionnaire d'événements jusqu'à ce que ce gestionnaire d'événements soit revenu. Vous pouvez le voir dans n'importe quelle application simplement. Installez un gestionnaire pour toute action IO (par exemple, une pression sur un bouton) qui est en veille. Vous allez bloquer la boucle d'exécution principale (et toute l'interface utilisateur) jusqu'à ce que cette méthode soit terminée.

La même chose s'applique à n'importe quelle boucle d'exécution.

Je vous suggère de lire la documentation suivante sur les boucles d’exécution:

https://developer.Apple.com/documentation/foundation/nsrunloop

et comment ils sont utilisés dans les threads:

https://developer.Apple.com/library/content/documentation/Cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html#//Apple_ref/doc/uid/10000057i-CH16-SW1

189
Jody Hagins

RunLoops est un peu comme une boîte où il se passe des choses.

En gros, dans un RunLoop, vous allez traiter certains événements, puis vous revenez. Ou retournez s'il ne traite aucun événement avant que le délai d'attente ne soit atteint. Vous pouvez le dire de la même manière que NSURLConnections asynchrones, Traitement des données en arrière-plan sans perturber votre boucle actuelle et en même temps, vous avez besoin de données de manière synchrone. Ce qui peut être fait avec l’aide de RunLoop qui rend votre NSURLConnection asynchrone et fournit des données au moment de l’appel. Vous pouvez utiliser un RunLoop comme ceci:

NSDate *loopUntil = [NSDate dateWithTimeIntervalSinceNow:0.1];

while (YourBoolFlag && [[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode beforeDate:loopUntil]) {
    loopUntil = [NSDate dateWithTimeIntervalSinceNow:0.1];
}

Dans ce RunLoop, il fonctionnera jusqu'à ce que vous ayez terminé votre travail et mis YourBoolFlag à false.

De même, vous pouvez les utiliser dans les discussions.

J'espère que cela vous aide.

8
Akshay Sunderwani

Les boucles d'exécution sont ce que sépare des applications interactives à partir de en ligne de commande outils.

  • Les outils de ligne de commande sont lancés avec des paramètres, exécutent leur commande, puis sortent.
  • Les applications interactives attendent la saisie de l'utilisateur, réagissent, puis reprennent l'attente.

De ici

Ils vous permettent d'attendre que l'utilisateur tape et de réagir en conséquence, d'attendre que vous obteniez un AchèvementHandler et d'appliquer ses résultats, d'attendre jusqu'à ce que vous obteniez une minuterie et d'effectuer une fonction. Si vous n'avez pas de boucle d'appel, vous ne pouvez pas écouter/attendre les taps de l'utilisateur, vous ne pouvez pas attendre qu'un appel réseau se produise, vous ne pouvez pas être réveillé dans x minutes.

Aussi de ce commentaire :

Les threads en arrière-plan n'ont pas leurs propres boucles, mais vous pouvez simplement en ajouter une. Par exemple. AFNetworking 2.x l'a fait. C'était une technique éprouvée pour NSURLConnection ou NSTimer sur les threads d'arrière-plan, mais nous ne le faisons plus nous-mêmes, car les nouvelles API éliminent le besoin de le faire. Mais il semble que URLSession exécute, par exemple, voici une simple requête , en exécutant [voir le panneau de gauche de l'image] les gestionnaires d'achèvement dans la file d'attente principale, et vous pouvez voir qu'il a une boucle d'exécution sur le fil d'arrière-plan

2
Honey

Les boucles d'exécution font partie de l'infrastructure fondamentale associée aux threads. Une boucle d'exécution est une boucle de traitement d'événements que vous utilisez pour planifier le travail et coordonner la réception des événements entrants. Le but d'une boucle d'exécution est de garder votre thread occupé quand il y a du travail à faire et de mettre votre thread en veille lorsqu'il n'y en a pas.

à partir d'ici


La caractéristique la plus importante de CFRunLoop est le CFRunLoopModes. CFRunLoop fonctionne avec un système de "Run Loop Sources". Les sources sont enregistrées sur une boucle d'exécution pour un ou plusieurs modes, et la boucle d'exécution elle-même est conçue pour s'exécuter dans un mode donné. Lorsqu'un événement arrive sur une source, il est uniquement géré par la boucle d'exécution si le mode source correspond au mode actuel de la boucle d'exécution.

à partir d'ici

0
dengApro