10
votes

Quelle file d'attente GCD, principale ou non, est-ce que je cours?

J'essaie d'écrire des méthodes de sécurité de threads afin que j'utilise: xxx pré>

mais si je suis sur le fil principal qui n'est pas nécessaire, et je peux ignorer tous ces appels d'expédition, Je voudrais donc savoir quel fil je suis actuellement. Comment puis-je savoir cela? P>

ou, peut-être que cela ne fait pas la différence (dans la performance) le faire? p>

est-ce correct de faire cette comparaison? P>

if (dispatch_get_main_queue() == dispatch_get_current_queue()){...}


3 commentaires

Pas seulement moins de frais généraux en utilisant l'une des techniques mentionnées, mais si vous faites une DISPATCH_SYNC à la même file d'attente, vous allez sur une impasse. Dispatch_ASync irait bien.


Si vous avez besoin d'une solution plus générique pour éviter toute impasse dans la libdispatch, consultez ces aides. Ils ne sont pas Cover Main_Queue, soyez juste prudent avec ça. Gist.github.com/1205760


La question est assez bonne mais le code de l'échantillon montre un motif d'impasse. Peut-être qu'il vaut mieux être modifié.


9 Réponses :


1
votes

Il n'est pas sûr d'utiliser Dispatch_Get_Current_Queue () sauf que vous ne déboguez pas. Comme il est clairement écrit dans le Dispatch_Queue Page d'homme :

CAVEATES

code ne peut apporter aucune hypothèse sur la file d'attente renvoyée par DisPatch_get_Current_Queue () . La file d'attente retournée peut avoir des politiques arbitraires pouvant surprendre le code qui essaie de planifier des travaux avec la file d'attente. La liste des politiques inclut, sans toutefois s'y limiter, la largeur de la file d'attente (c'est-à-dire la série en série parallèle), la planification de la priorité, des informations d'identification de sécurité ou du système de fichiers. Par conséquent, Dispatch_Get_Current_Queue () ne doit être utilisé que pour les tests d'identité ou le débogage.

La meilleure chose (peut être plus compliquée) consiste à synchroniser les threads de fond: xxx

peut-être que je suis totalement faux, mais c'est ce que je suggère.


1 commentaires

Dit clairement "des tests d'identité" comme bon. C'est ce que la question initiale allouée à (bien que cela ne fonctionne pas comme je l'ai mentionné dans ma réponse).



2
votes

Si vous êtes dans l'objectif-c et que vous voulez que quelque chose se produise sur le fil principal de manière synchrone, ne serait-il pas plus simple d'utiliser

[self performSelectorOnMainThread: @selector(doSomethingInTheForeground) 
                       withObject: nil 
                    waitUntilDone: YES];


0 commentaires

13
votes

réponse mise à jour :

Les Documents Apple ont changé et disent maintenant "lorsque cela s'appelle de l'extérieur du contexte d'un bloc soumis, cette fonction renvoie la file d'attente principale si l'appel est exécuté à partir du fil principal. Si l'appel est fabriqué à partir d'un autre fil, Cette fonction renvoie la file d'attente simultanée par défaut. " Donc, vérifier Dispatch_Get_Main_Queue () == Dispatch_Get_Current_Queue () devrait fonctionner.

réponse originale :

Utiliser Dispatch_Get_Main_Quue () == Dispatch_Get_Current_Queue () ne fonctionnera pas. Les docs pour DISPATCH_GET_CURRENT_QUEUE SOIT "Lorsque vous l'appellez à l'extérieur du contexte d'un bloc soumis, cette fonction renvoie la file d'attente simultanée par défaut". La file d'attente simultanée par défaut n'est pas la file d'attente principale.

[nsthread ismainthead] devrait fonctionner pour ce que vous voulez. Notez que [nsthread ismainthead] peut être vrai pour les files d'attente autres que la file d'attente principale, par exemple, lorsque vous appelez DisPatch_Sync du fil principal.


4 commentaires

En fait, il est indiqué "quand appelé de l'extérieur du contexte d'un bloc soumis, cette fonction renvoie la file d'attente principale si l'appel est exécuté à partir du fil principal . Si l'appel est fabriqué à partir d'un autre fil, Cette fonction renvoie la file d'attente simultanée par défaut. "


Merci beaucoup pour la mise à jour. Je pense que c'est la façon dont nous nous attendons tous à ce que cela fonctionne comme :)


On dirait que Dispatch_get_Current_Queue () est obsolète maintenant, quelle est une alternative?


Vous devriez utiliser Dispatch_Get_Specific. Voir Stackoverflow.com/a/15725847/412916 et le lien vers les forums Apple dans les commentaires.



0
votes

En réalité, il est correct d'utiliser.

La documentation dit

Lorsqu'il est appelé de l'extérieur du contexte d'un bloc soumis, cela fonction renvoie la file d'attente principale si l'appel est exécuté de la principale Fil . Si l'appel est fabriqué à partir d'un autre fil, cette fonction renvoie la file d'attente simultanée par défaut.


0 commentaires

4
votes

Réponse mise à jour:

Dispatch_Get_Current_Queue () est maintenant obsolète.

Réponse originale:

sur OS-X 10.8, dans le fichier d'en-tête (file d'attente.h), dans le commentaire ci-dessus la fonction Dispatch_Get_Current_Queue (), il est écrit:

lorsque DISPATCH_GET_CURrent_Queue () est appelé sur le fil principal, il peut ou peut ne pas renvoyer la même valeur que DISPATCH_GET_MAIN_QUEUE (). La comparaison des deux n'est pas un moyen valide de tester si le code exécute sur le fil principal.

J'ai découvert que c'est à cause d'un

ASSERT (DISTATCH_GET_CURrent_QUEUE () == Dispatch_Get_Main_Queue ());

dans mon code qui fonctionne bien sur iOS mais échoue sur OS-X.


0 commentaires

-1
votes

Dispatch_Get_Current_Queue est obsolète à partir de IOS 6.0. Ressemble à [nsthread ismainthead] est le seul moyen d'aller.


3 commentaires

J'ai vu l'usage de Dispatch_get_Main_Queue dans de nombreux tutoriels et documentation d'Apple et de tiers. Il semble que ce soit une fonction très largement utilisée. Je défie là que cela est obsolète en général. Pouvez-vous donner des références? Existe-t-il une stratégie de remplacement directe?


Vous êtes correct, je coupe / coller le nom de la fonction incorrecte. C'est Dispatch_get_Current_Queue qui a été obsolète. Désolé pour la confusion. Cependant, la conclusion tient toujours. [Nsthread ismainthread] est le seul moyen d'aller (même s'il ne signifie pas toujours que vous êtes dans la file d'attente principale).


Aha, aussi nouveau pour moi, mais oui je suis d'accord. :)



12
votes

avec amortissement de DisPatch_Get_Current_Queue () , l'équivalent de (DisPatch_Get_Main_Quue () == Dispatch_Get_Current_Queue ())

est maintenant en comparaison de l'étiquette de la file d'attente qui est: < / p> xxx


1 commentaires

Notez que DisPatch_Queue_Get_Label () renvoie un char *. Est-il suffisant de vérifier les valeurs du pointeur renvoyées par les deux appels? Est-ce qu'une STRCMP () appelle redondant?



0
votes

Notez que la file d'attente principale n'est pas la même que le fil principal. Il est facilement possible qu'une file d'attente non principale fonctionne sur le fil principal, lorsque DisPatch_Sync () est utilisé sur une file d'attente du fil principal. Beaucoup plus rarement, dans des outils de ligne de commande qui utilisent Dispatch_Main () au lieu de NsRunloops (c'est-à-dire autre que les applications de cacao / iOS), il est possible que la file d'attente principale soit exécutée dans autre chose que le fil principal.

Si vous traitent du code qui nécessite la file d'attente principale et non seulement le fil principal (par exemple le code qui s'attend à ce que les valeurs définies sur la file d'attente principale de la queue_get_specific, que Vectorkit / Mapkit a été rumée à faire), il est préférable de vérifier la file d'attente principale explicitement plutôt que le fil principal.

une option pour vérifier explicitement la file d'attente principale: xxx

la réponse à l'aide de DisPatch_Current_Queue_Label devrait également fonctionner et est probablement mieux , bien que peut ne pas fonctionner (c.-à-d. Crash) avant MacOS 10.9 et iOS7, lorsque DisPatch_Current_Queue_Label a été défini.


0 commentaires

3
votes

Nouveau pour iOS: 10.0+ et MacOS: 10.12+ (TVOS: 10.0+, Watchos: 3.0 +).

Swift 4 +: H2>

Vérifiez si vous utilisez la file d'attente principale: P >

dispatch_assert_queue_not(dispatch_get_main_queue());

0 commentaires