Kuidas töötavad async ja await mehhanismid kapoti all?
sobes.tech AI
Vastus AI-lt
Swiftis põhineb Async/await struktureeritud konkurentsil ning kasutab Dispatch/Global Actors. Põhjalikumalt töötavad järgmised mehhanismid:
-
Jätkamisstiil: Asünkroonfunktsioonid kompileeritakse jätkamistiiliks. Selle asemel, et kohe väärtust tagastada, edastatakse juhtimine Swift'i jooksutajale, mis salvestab funktsiooni praeguse oleku (kohalikud muutujad, täitmise näitaja). Kui asünkroonne operatsioon lõpeb, jätkab jooksutaja funktsiooni salvestatud olekust.
-
Ülesanne: Iga
asyncfunktsiooni väljakutse loob või ühineb struktureeritudTask-ga.Taskesindab tööühikut ning loob hierarhia. Vanem-Taskootab, kuni alam-Task-id on lõpetatud. -
Töö:
Taskjaguneb väiksemateks tööüksusteks, mida nimetatakseJob-deks.Jobon koodilõik, mida saab täita täitjal (Executor). -
Täitev: Täitja vastutab
Job-i käivitamise eest. Standardraamatukogus kasutatakse peamiselt globaalsetDispatchQueue-d täitjatena enamikule asünkroonsetele ülesannetele. Spetsiifilised kontekstid (näiteksMainActor) kasutavad oma spetsialiseeritud täitjaid. -
Arestuspunktid:
awaiton peatamispunkt. Kui jõutakseawait-i, peatub funktsioon, juhtimine antakse väljakutsele või täitjale ning praeguneJoblõpetatakse. Swift'i jooksutaja salvestab funktsiooni oleku. -
Taaskäivitamine: Kui oodatud asünkroonne operatsioon lõpeb, loob Swift'i jooksutaja uue
Jobjätkamiseks peatatud funktsiooni. SeeJoblisatakse täitja järjekorda. -
Tühistamine: Struktureeritud konkurents toetab hierarhilist tühistamist. Vanem-
Tasktühistamine tühistab automaatselt kõik selle lapsed-Task-id. Asünkroonsetel operatsioonidel võib olla kontroll tühistamise staatuse üle ning reageerida vastavalt.
Siin on lihtsustatud näide async funktsiooni kompileerimisest:
// Algne async funktsioon
func fetchData() async -> Data {
// Asünkroonne operatsioon
let data = await URLSession.shared.data(from: url).0
return data
}
// Lihtsustatud kompileerimise näide
// Selle asemel, et tagastada, funktsioon võtab vastu Continuation
func fetchData(_ continuation: Continuation<Data, Error>) {
// Funktsiooni algus
let url = URL(string: "...")! // Näide
// Asünkroonse operatsiooni käivitamine
URLSession.shared.data(from: url) { data, _, error in
// See sulg täidetakse pärast asünkroonse operatsiooni lõppu
if let data = data {
// Saadetakse tulemus continuation-ile, jätkates funktsiooni
continuation.resume(returning: data)
} else if let error = error {
continuation.resume(throwing: error)
} else {
// Muud juhtumid
continuation.resume(throwing: NSError(domain: "", code: 0, userInfo: nil))
}
}
// Funktsioon lõpeb siin, ootab `resume`-i kutsumist continuation-ilt
}
Await on sisuliselt süntaksisuhkur Continuation-i haldamise ja Job-i planeerimise üle täitjal. Peatamine ei blokeeri otseselt niidi, vaid võimaldab täitjal täita teisi Job-e.