- Published on
Async va Await qanday ishlashi: Thread'lar va Kutish
- Authors
- Name
- ShoxruxC
- @iOSdasturchi
Async va Await haqiqatda qanday ishlaydi?
Oldingi darsimizda rasmni asinxron yuklab olish orqali async/await qanday yozilishini ko'rgan edik. Ammo bu kalit so'zlar kodimizda aniq nima vazifani bajarmoqda? Nimani o'zgartirmoqda? Ushbu qisqa maqolada biz kod ortidagi jarayonlar — "Thread" lar va kutish nuqtalarini tahlil qilamiz.
Avval: Thread'larni qo'lda boshqarish (DispatchQueue)
Swift Concurrency paydo bo'lgunga qadar, og'ir vazifalarni orqa fonga o'tkazish uchun biz aniq (explicitly) tizimga qaysi thread'ga (oqimga) o'tishni aytishimiz kerak edi.
Masalan, orqa fonda ma'lumotni hisoblab, keyin Ekranni (UI) yangilash uchun Asosiy oqimga (Main thread) qaytish quyidagicha yozilardi:
func addTitle() {
// 1. Orqa fonga o'tish (Global thread)
DispatchQueue.global().async {
let title = "Yangi sarlavha" // Og'ir hisoblash jarayoni...
// 2. Ekranni yangilash uchun Asosiy oqimga qaytish
DispatchQueue.main.async {
self.dataArray.append(title)
}
}
}
Endi: Async va Await orqali avtomatik boshqaruv
Endi biz DispatchQueue'lardan umuman foydalanmaymiz. O'rniga async va await kalit so'zlarini ishlatamiz.
func addAuthor() async {
// 2 soniya (2 milliard nanosekund) kutib turamiz (Tarmoqdagi kechikishni simulyatsiya qilyapmiz)
try? await Task.sleep(nanoseconds: 2_000_000_000)
let author = "Muallif 1 : \(Thread.current)"
// UI'ni yangilash uchun Asosiy oqimga qaytamiz
await MainActor.run {
self.dataArray.append(author)
}
}
Bu yerda siz e'tibor qaratishingiz kerak bo'lgan juda muhim jihatlar bor:
1. Await — bu "Kutish nuqtasi" (Suspension point)
Siz qachonki await so'zini ishlatsangiz, dastur bajarilishi o'sha nuqtada to'xtaydi (suspend qilinadi) va natija qaytguncha kutib turadi. Lekin bu butun ilova qotib qoladi degani emas! U faqat o'zi joylashgan asinxron Task ning shu qatorigina to'xtatib, boshqa operatsiyalarga (masalan UI animatsiyalariga) xalaqit bermasdan orqa fonda ishlashda davom etadi.
2. Thread'lar siri
Biz DispatchQueue.global() deb orqa fonga o'tishni buyurmadik. Lekin try? await Task.sleep(...) tugab, keyingi qator o'qilayotganda biz qaysidir orqa thread'da (Thread 2, 3, 5 va hokazo) bo'lamiz.
Qoida: await dan so'ng kod qaysi thread'da ishlashini biz aniq bilmaymiz. U fonda istalgan bo'sh thread'dan foydalanishi mumkin. Aynan shuning uchun, funksiya yakunida har doim xavfsizlik uchun await MainActor.run orqali UI kodlarini Asosiy oqimda (Main Threadda) ekanligimizni kafolatlab bajarishimiz shart.
Ketma-ketlik (Sinxron ko'rinishdagi Asinxron kod)
Agar biz ViewModel'da bir nechta asinxron funksiyalarni chaqirsak nima bo'ladi?
func onAppear() {
// Asinxron muhitga kiramiz
Task {
// 1-kutish
await addAuthor()
// 2-kutish
await addSomethingElse()
let final = "Yakuniy matn"
self.dataArray.append(final)
}
}
Garchi bu kod asinxron bo'lsa ham, u xuddi sinxron kod kabi tepadan pastga qarab, bitta-bitta ishlaydi. Ya'ni:
addAuthor()ishlashni boshlaydi. Bizawaitso'zi borligi uchun u o'z ishini to'liq tugatmaguncha pastga o'tmaymiz. Dastur shu qatorda kutadi.addAuthor()tugagach,addSomethingElse()ishlashni boshlaydi. U ham o'z ishini tugatmaguncha kutamiz.- Hammasi tayyor bo'lgach, oxirgi qatordagi
finalmatni ro'yxatga qo'shiladi.
Bu async/await ning eng katta ustunligi hisoblanadi. Kodni o'qish judayam onson — birinchi qator tugamasdan ikkinchisiga o'tmaydi.
Xulosa
asyncfunksiyalar bizni explicitly (qo'lda) thread'larni boshqarishdan qutqaradi.awaitkalit so'zi kodning o'sha joyida natija kelguncha "muzlatib" (suspend) qo'yadi.- Asinxron operatsiya tugagandan so'ng, qaysi thread'daligimiz noma'lum bo'ladi, shu sababli UI ni o'zgartiradigan qismini doimo
MainActoryordamida himoyalashimiz kerak. awaitkodlarni parallel tarzda emas, aksincha ularni xavfsiz holda ketma-ket bajarilishini ta'minlaydi. (Kodni qanday qilib bir vaqtda parallel bajarish kerakligini esa kelgusi darslarda ko'rib chiqamiz).