62 votes

Comment répartir la file d'attente principale de manière synchrone sans impasse?

J'ai besoin d'envoyer un bloc sur la file d'attente principale, de façon synchrone. Je ne sais pas si je suis actuellement en cours d'exécution sur le thread principal ou non. La solution naïve ressemble à ceci:

dispatch_sync(dispatch_get_main_queue(), block);

Mais si je suis actuellement à l'intérieur d'un bloc en cours d'exécution sur la file d'attente principale, cet appel crée un blocage. (Synchrone expédition attend pour le bloc à la fin, mais le bloc ne même pas commencer à courir, puisque nous sommes en attente de l'actuel à la fin.)

L'étape logique suivante est de vérifier pour la file d'attente en cours:

if (dispatch_get_current_queue() == dispatch_get_main_queue()) {
    block();
} else {
    dispatch_sync(dispatch_get_main_queue(), block);
}

Cela fonctionne, mais c'est moche. Avant, j'ai au moins le cacher derrière une certaine fonction personnalisée, n'est-il pas une meilleure solution pour ce problème? Je tiens à souligner que je ne peux pas se permettre de l'envoi de ce bloc de manière asynchrone – l'app est dans une situation où le mode asynchrone distribué bloc exécuté "trop tard".

70voto

Brad Larson Points 122629

J'ai besoin d'utiliser quelque chose comme ceci assez régulièrement dans mon Mac et iOS applications, j'utilise donc la fonction d'assistance suivante (initialement décrite dans cette réponse):

void runOnMainQueueWithoutDeadlocking(void (^block)(void))
{
    if ([NSThread isMainThread])
    {
        block();
    }
    else
    {
        dispatch_sync(dispatch_get_main_queue(), block);
    }
}

qui vous appel à l'aide

runOnMainQueueWithoutDeadlocking(^{
    //Do stuff
});

C'est à peu près le processus que vous décrivez ci-dessus, et j'ai parlé à plusieurs autres développeurs qui ont conçu indépendamment quelque chose comme cela pour eux-mêmes.

J'ai utilisé [NSThread isMainThread] au lieu de vérifier dispatch_get_current_queue(), parce que les mises en garde de la section pour cette fonction une fois mis en garde contre l'utilisation de ce pour test d'identité, et l'appel a été déprécié dans iOS 6.

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