Perché la concorrenza?
Non appena aggiungi attività pesanti alla tua app come il caricamento dei dati, rallenta il lavoro dell'interfaccia utente o addirittura la blocca. La concorrenza consente di eseguire 2 o più attività "contemporaneamente". Lo svantaggio di questo approccio è che la sicurezza del thread non è sempre facile da controllare. Senti quando attività diverse vogliono accedere alle stesse risorse come provare a cambiare la stessa variabile su thread diversi o accedere alle risorse già bloccate dai diversi thread.
Ci sono alcune astrazioni di cui dobbiamo essere consapevoli.
- Code.
- Prestazioni delle attività sincrone / asincrone.
- Priorità.
- Problemi comuni.
Code
Deve essere seriale o simultaneo . Oltre che globale o privato allo stesso tempo.
Con le code seriali, le attività verranno completate una per una mentre con le code simultanee, le attività verranno eseguite simultaneamente e saranno terminate secondo pianificazioni impreviste. Lo stesso gruppo di attività richiederà più tempo su una coda seriale rispetto a una coda simultanea.
Puoi creare le tue code private (sia seriali che simultanee ) o utilizzare le code globali (di sistema) già disponibili . La coda principale è l'unica coda seriale tra tutte le code globali .
Si consiglia vivamente di non eseguire attività pesanti che non sono riferite al lavoro dell'interfaccia utente sulla coda principale (ad esempio il caricamento dei dati dalla rete), ma invece di eseguirle sulle altre code per mantenere l'interfaccia utente non congelata e reattiva alle azioni dell'utente. Se lasciamo che l'interfaccia utente venga modificata sulle altre code, le modifiche possono essere apportate a una pianificazione e velocità diverse e inaspettate. Alcuni elementi dell'interfaccia utente possono essere disegnati prima o dopo che sono necessari. Può mandare in crash l'interfaccia utente. Dobbiamo anche tenere presente che poiché le code globali sono code di sistema, ci sono alcune altre attività che possono essere eseguite dal sistema su di esse.
Qualità del servizio / Priorità
Le code hanno anche diversi qos (Quality of Service) che imposta la priorità di esecuzione
dell'attività (dalla più alta alla più bassa qui): .userInteractive - coda principale
.userInitiated - per le attività avviate dall'utente su cui l'utente attende una risposta
.utility - per le attività che richiede un po 'di tempo e non richiede una risposta immediata, ad esempio lavorare con i dati
.background - per le attività che non sono correlate alla parte visiva e che non sono rigide per il tempo di completamento).
C'è anche
una coda .default che non trasferisce le informazioni di qos . Se non è stato possibile rilevare il qos, il file qosverrà utilizzato tra .userInitiated e .utility .
Le attività possono essere eseguite in modo sincrono o asincrono .
La funzione sincrona restituisce il controllo alla coda corrente solo al termine dell'attività. Blocca la coda e attende fino al termine dell'attività.
La funzione asincrona restituisce il controllo alla coda corrente subito dopo che l'attività è stata inviata per essere eseguita sulla coda diversa. Non attende che l'attività sia terminata. Non blocca la coda.
Problemi comuni.
Gli errori più popolari commessi dai programmatori durante la proiezione delle app simultanee sono i seguenti:
- Condizione di gara : causata quando il funzionamento dell'app dipende dall'ordine di esecuzione delle parti di codice.
- Inversione di priorità : quando le attività con priorità più alta attendono il completamento delle attività con priorità più bassa a causa del blocco di alcune risorse
- Deadlock : quando alcune code hanno un'attesa infinita per le origini (variabili, dati ecc.) Già bloccate da alcune di queste code.
Non chiamare MAI la funzione di sincronizzazione sulla coda principale .
Se chiami la funzione di sincronizzazione sulla coda principale, questa bloccherà la coda così come la coda sarà in attesa del completamento dell'attività ma l'attività non sarà mai terminata poiché non sarà nemmeno in grado di avviarsi perché la coda è già bloccato. Si chiama deadlock .
Quando utilizzare la sincronizzazione?
Quando è necessario attendere fino al termine dell'attività. Sentite quando ci assicuriamo che qualche funzione / metodo non venga chiamato due volte. Sentiamo che abbiamo la sincronizzazione e cerchiamo di impedire che venga chiamato due volte fino a quando non è completamente finito. Ecco un po 'di codice per questa preoccupazione:
come scoprire cosa ha causato il rapporto di arresto anomalo dell'errore sul dispositivo IOS?
DispatchQueue.main.sync
da un thread in background?