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.
- Performances des tâches synchrones / asynchrones.
- Priorités.
- Problèmes courants.
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:
- Condition de concurrence - causée lorsque le travail de l'application dépend de l'ordre d'exécution des parties de code.
- Inversion de priorité - lorsque les tâches de priorité plus élevée attendent que les tâches de priorité plus petites soient terminées en raison du blocage de certaines ressources
- Deadlock - lorsque quelques files d'attente ont une attente infinie pour les sources (variables, données, etc.) déjà bloquées par certaines de ces files d'attente.
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?
DispatchQueue.main.sync
partir d'un fil d'arrière-plan?