104 votes

Alternatives à dispatch_get_current_queue () pour les blocs de complétion sous iOS 6?

J'ai une méthode qui accepte un bloc et un bloc d'achèvement. Le premier bloc doit être exécuté en arrière-plan, tandis que le bloc d'achèvement doit être exécuté dans la file d'attente de la méthode.

Pour ce dernier, j'ai toujours utilisé dispatch_get_current_queue() , mais il semble que cela soit déconseillé dans iOS 6 ou supérieur. Que devrais-je utiliser à la place?

65voto

Catfish_Man Points 15439

Le modèle de "l'exécuter sur n'importe quel file d'attente de l'appelant était" est séduisante, mais finalement pas une bonne idée. Cette file d'attente pourrait être une priorité de la file d'attente, la file d'attente principale, ou une autre file d'attente avec de curieuses propriétés.

Mon approche préférée pour ce est-à-dire "la fin du bloc s'exécute sur une mise en œuvre définies file d'attente avec les propriétés suivantes: x, y, z", et de laisser le bloc d'envoi à une file d'attente particulière si l'appelant veut plus de contrôle que cela. Typique d'un ensemble de propriétés pour spécifier serait quelque chose comme "série, non réentrant, et asynchrone par rapport à tout autre visible par l'application de la file d'attente".

27voto

jkh Points 2015

C'est fondamentalement l'approche erronée de l'API que vous décrivez à prendre. Si une API accepte un bloc et l'achèvement de bloc à exécuter, les faits suivants doivent être remplies:

  1. Le "bloc à exécuter" doit être exécuté sur une file d'attente interne, par exemple une file d'attente qui est privé de l'API et donc entièrement sous l'API de contrôle. La seule exception à cette règle est si l'API spécifiquement déclare que le bloc sera exécuté sur la file d'attente principale ou l'une des mondiale simultanée des files d'attente.

  2. L'achèvement de bloc doit toujours être exprimée comme un n-uplet (file d'attente, bloc), à moins que les mêmes hypothèses que pour le #1 vrai, par exemple l'achèvement du bloc sera exécuté sur une connues dans le monde de la file d'attente. L'achèvement de bloc doit en outre être distribué asynchrone sur le passé-dans la file d'attente.

Ce ne sont pas seulement stylistique points, ils sont tout à fait nécessaire si votre API est d'être à l'abri de blocages ou de l'autre bord de cas d'un comportement qui, autrement, accrochez vous à partir de l'arbre le plus proche, un jour. :-)

15voto

Yar Points 25421

Les autres réponses sont excellentes, mais pour moi la réponse est structurelle. J'ai une méthode comme celle-ci qui est sur un Singleton:

 - (void) dispatchOnHighPriorityNonMainQueue:(simplest_block)block forceAsync:(BOOL)forceAsync {
    if (forceAsync || [NSThread isMainThread])
        dispatch_async_on_high_priority_queue(block);
    else
        block();
}
 

qui a deux dépendances, qui sont:

 static void dispatch_async_on_high_priority_queue(dispatch_block_t block) {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), block);
}
 

et

 typedef void (^simplest_block)(void); // also could use dispatch_block_t
 

De cette façon, je centralise mes appels pour envoyer sur l'autre thread.

12voto

WDUK Points 11893

Vous devez être prudent au sujet de votre utilisation de l' dispatch_get_current_queue dans la première place. À partir du fichier d'en-tête:

Recommandé pour le débogage et la journalisation seulement:

Le code ne doit pas faire d'hypothèses sur la file d'attente retourné, à moins qu'il est l'un des grands files d'attente ou une file d'attente, le code a lui-même créé. Le code ne doit pas supposer que l'exécution synchrone sur une file d'attente est sécurité de blocage si la file d'attente n'est pas celui retourné par dispatch_get_current_queue().

Vous pourriez faire une de deux choses:

  1. De conserver une référence à la file d'attente vous avez posté sur (si vous l'avez créé via dispatch_queue_create), et de l'utiliser ensuite.

  2. L'utilisation du système de files d'attente via dispatch_get_global_queue, et de garder une trace de celui que vous utilisez.

Effectivement, alors compter sur le système pour garder une trace de la file d'attente, vous êtes sur, vous allez avoir à le faire vous-même.

4voto

alexey.hippie Points 190

Pour ceux qui ont encore besoin de comparer dans la file d'attente, vous pouvez comparer les files d'attente par leur libellé ou leur spécification. Vérifiez cette http://stackoverflow.com/a/23220741/1531141

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X