J'utilise depuis DispatchQueue.main.async
longtemps pour effectuer des opérations liées à l'interface utilisateur.
Swift fournit à la fois DispatchQueue.main.async
et DispatchQueue.main.sync
, et les deux sont exécutés sur la file d'attente principale.
Quelqu'un peut-il me dire la différence entre eux? Quand devrais-je utiliser chacun?
DispatchQueue.main.async {
self.imageView.image = imageView
self.lbltitle.text = ""
}
DispatchQueue.main.sync {
self.imageView.image = imageView
self.lbltitle.text = ""
}
la source
DispatchQueue.main.sync
partir d'un fil d'arrière-plan?async
là-bas? Je veux dire, puisqu'il n'y a rien d'autre sur le fil après, cela ne fait aucune différence. Si c'était le cas, celaDispatchQueue.main.sync {block1}; DispatchQueue.main.sync {block2};
aurait eu du sens. Mais quand il n'y a pas d'autre bloc, je ne peux pas penser à l'avantage d'utiliserDispatchQueue.main.sync {Oneblock}
overDispatchQueue.main.async {Oneblock}
. Pour les deux, ils obtiendront la priorité / l'immédiateté mainQueue et rien ne les interrompra.Pourquoi la concurrence?
Dès que vous ajoutez des tâches lourdes à votre application, comme le chargement de données, cela ralentit le travail de votre interface utilisateur ou même la gèle. La simultanéité vous permet d'effectuer 2 tâches ou plus «simultanément». L'inconvénient de cette approche est que la sécurité des fils n'est pas toujours aussi facile à contrôler. Fe lorsque différentes tâches veulent accéder aux mêmes ressources, comme essayer de modifier la même variable sur un autre thread ou accéder aux ressources déjà bloquées par les différents threads.
Il y a quelques abstractions dont nous devons être conscients.
Files d'attente
Doit être en série ou simultané . Ainsi que global ou privé en même temps.
Avec les files d'attente en série, les tâches seront terminées une par une, tandis qu'avec les files d'attente simultanées, les tâches seront exécutées simultanément et seront terminées selon des horaires inattendus. Le même groupe de tâches prendra beaucoup plus de temps sur une file d'attente série par rapport à une file d'attente simultanée.
Vous pouvez créer vos propres files d'attente privées (en série ou simultanées ) ou utiliser des files d'attente globales (système) déjà disponibles . La file d'attente principale est la seule file d'attente série parmi toutes les files d'attente globales .
Il est fortement recommandé de ne pas effectuer de tâches lourdes qui ne font pas référence au travail de l'interface utilisateur sur la file d'attente principale (par exemple, le chargement de données à partir du réseau), mais plutôt de les effectuer sur les autres files d'attente pour que l'interface utilisateur reste dégelée et réagisse aux actions de l'utilisateur. Si nous laissons l'interface utilisateur être modifiée sur les autres files d'attente, les modifications peuvent être effectuées selon un horaire et une vitesse différents et inattendus. Certains éléments de l'interface utilisateur peuvent être dessinés avant ou après leur utilisation. Cela peut planter l'interface utilisateur. Nous devons également garder à l'esprit que, puisque les files d'attente globales sont des files d'attente système , d'autres tâches peuvent être exécutées par le système.
Qualité de service / priorité
Les files d'attente ont également des qos (qualité de service) différents qui définissent la priorité d' exécution de la tâche (du plus élevé au plus bas ici):
.userInteractive - file d'attente principale
.userInitiated - pour les tâches lancées par l'utilisateur sur lesquelles l'utilisateur attend une réponse
.utility - pour les tâches qui prend un certain temps et ne nécessite pas de réponse immédiate, par exemple travailler avec des données
.background - pour les tâches qui ne sont pas liées à la partie visuelle et qui ne sont pas strictes pour le temps de réalisation).
Il existe également
une file d'attente .default qui ne transfère pas les informations qos . S'il n'était pas possible de détecter le qos, leqos sera utilisé entre .userInitiated et .utility .
Les tâches peuvent être effectuées de manière synchrone ou asynchrone .
La fonction synchrone renvoie le contrôle de la file d'attente actuelle uniquement une fois la tâche terminée. Il bloque la file d'attente et attend que la tâche soit terminée.
La fonction asynchrone retourne le contrôle à la file d'attente actuelle juste après que la tâche a été envoyée pour être effectuée sur la file d'attente différente. Il n'attend pas que la tâche soit terminée. Cela ne bloque pas la file d'attente.
Problèmes courants.
Les erreurs les plus courantes commises par les programmeurs lors de la projection des applications simultanées sont les suivantes:
N'appelez JAMAIS la fonction de synchronisation sur la file d'attente principale .
Si vous appelez la fonction de synchronisation sur la file d'attente principale, elle bloquera la file d'attente et la file d'attente attendra que la tâche soit terminée, mais la tâche ne sera jamais terminée car elle ne pourra même pas démarrer car la file d'attente est déjà bloqué. Cela s'appelle une impasse .
Quand utiliser la synchronisation? Lorsque nous devons attendre que la tâche soit terminée. Fe lorsque nous nous assurons qu'une fonction / méthode n'est pas appelée en double. Fe nous avons la synchronisation et essayons de l'empêcher d'être doublé jusqu'à ce qu'elle soit complètement terminée. Voici un code pour ce problème:
Comment savoir ce qui a provoqué le rapport d'erreur sur le périphérique IOS?
la source
DispatchQueue.main.sync
partir d'un fil d'arrière-plan?sync
ou lesasync
méthodes n'ont aucun effet sur la file d'attente sur laquelle elles sont appelées.sync
bloquera le thread à partir duquel il est appelé et non la file d' attente sur laquelle il est appelé. C'est la propriétéDispatchQueue
qui décide si leDispatchQueue
va attendre l'exécution de la tâche (file d'attente série) ou peut exécuter la tâche suivante avant que la tâche en cours ne soit terminée (file d'attente simultanée).Ainsi, même en cas
DispatchQueue.main.async
d'appel asynchrone, une opération lourde ajoutée peut geler l'interface utilisateur lorsque ses opérations sont exécutées en série sur le thread principal. Si cette méthode est appelée à partir du thread d'arrière-plan, le contrôle retournera instantanément à ce thread même lorsque l'interface utilisateur semble figée. C'est parce que l'async
appel est passéDispatchQueue.main
la source
GCD
vous permet d'exécuter une tâchesynchronously
ouasynchronously
[À propos] [Plus]synchronous
(bloquer et attendre) la fonction retourne un contrôle lorsque la tâche sera terminéeasynchronous
(expédier et procéder) renvoie un contrôle immédiatement, distribuant la tâche pour qu'elle démarre dans une file d'attente appropriée mais sans attendre qu'elle se termine.la source