- Published on
Swiftda Task va TaskGroup
- Authors
- Name
- ShoxruxC
- @iOSdasturchi
Task β Swift Concurrency ning asosiy qurilish bloki. U asinxron ishni "o'rab oluvchi" birlik bo'lib, sinxron koddan async kodni boshlash imkonini beradi. Masalan, SwiftUI da Button ichida tarmoq so'rovi yuborishingiz kerak bo'lsa β Task { } bloki ichiga yozasiz.
TaskGroup β bir nechta parallel vazifani boshqarish uchun ishlatiladigan tuzilma. Masalan, 10 ta rasmni bir vaqtda yuklash kerak bo'lganda, har biri uchun alohida vazifa yaratib, barcha natijalarni yig'ish mumkin. Bu structured concurrency deb ataladi β barcha vazifalar boshqariladigan tizim ichida ishlaydi.
Task yaratish
Task { } β eng oddiy usul. U yangi asinxron vazifa yaratadi va darhol ishga tushiradi. Sinxron kod esa kutmaydi β davom etadi. Agar natijani olish kerak bo'lsa, task.value xususiyati await bilan ishlatiladi.
// βββββββββββββββββββββββββββββββββββββββ
// TASK β sinxron kontekstdan async boshlash
// βββββββββββββββββββββββββββββββββββββββ
func sinxronFunksiya() {
print("1. Sinxron boshlanmoqda")
// Task β yangi asinxron vazifa yaratadi
Task {
// Bu kod asinxron bajariladi
let natija = try await tarmoqSorovi()
print("3. Natija: \(natija)")
}
// Task yaratildi, lekin kutilmaydi β davom etadi
print("2. Sinxron davom etmoqda")
}
// Chiqadi: 1, 2, 3 (3 keyinroq)
// βββββββββββββββββββββββββββββββββββββββ
// TASK NATIJASINI OLISH
// βββββββββββββββββββββββββββββββββββββββ
func natijaniOlish() async {
let task = Task {
try await tarmoqSorovi()
}
// task.value β natijani kutish
do {
let natija = try await task.value
print("Natija: \(natija)")
} catch {
print("Xato: \(error)")
}
}
func tarmoqSorovi() async throws -> String {
try await Task.sleep(for: .seconds(1))
return "Ma'lumot yuklandi"
}
Task bekor qilish (cancellation)
Muhim tushuncha: task.cancel() chaqirilganda vazifa darhol to'xtamaydi! Bu faqat signal yuboradi. Vazifa o'zi ichida Task.isCancelled ni tekshirishi va kerak bo'lganda to'xtashi kerak. Bu kooperativ bekor qilish deb ataladi β vazifa o'zi qaror qabul qiladi. Bu xavfsiz, chunki vazifa to'xtashdan oldin resurslarni tozalashi mumkin.
// βββββββββββββββββββββββββββββββββββββββ
// CANCEL β vazifani bekor qilish
// Muhim: cancel() darhol to'xtatmaydi!
// Vazifa o'zi isCancelled ni tekshirishi kerak
// βββββββββββββββββββββββββββββββββββββββ
class YuklovchiViewModel {
private var yuklovchiTask: Task<Void, Never>?
func yuklashBoshla() {
// Avvalgi vazifani bekor qilish
yuklovchiTask?.cancel()
yuklovchiTask = Task {
for sahifa in 1...100 {
// Har iteratsiyada bekor qilinganligini tekshirish
guard !Task.isCancelled else {
print("Bekor qilindi! Sahifa: \(sahifa)")
return
}
try? await Task.sleep(for: .milliseconds(100))
print("Sahifa \(sahifa) yuklandi")
}
}
}
func yuklashTo'xtat() {
yuklovchiTask?.cancel()
// Signal yuborildi β keyingi isCancelled tekshiruvida to'xtaydi
}
}
let vm = YuklovchiViewModel()
vm.yuklashBoshla()
// 2 soniyadan keyin to'xtatish
Task {
try await Task.sleep(for: .seconds(2))
vm.yuklashTo'xtat()
}
TaskGroup β parallel vazifalar guruhi
withTaskGroup β bir nechta vazifani parallel ishga tushirish va natijalarini bir joyga yig'ish uchun ishlatiladi. guruh.addTask { } bilan yangi vazifa qo'shiladi, for await natija in guruh bilan natijalar ketma-ket yig'iladi. Agar xato tashlashi mumkin bo'lgan vazifalar kerak bo'lsa β withThrowingTaskGroup ishlatiladi. Unda bitta vazifa xato tashlasa, qolgan barcha vazifalar avtomatik bekor qilinadi.
// βββββββββββββββββββββββββββββββββββββββ
// TASKGROUP β ko'p vazifani parallel bajarish
// βββββββββββββββββββββββββββββββββββββββ
func rasmlarniYukla(idlar: [Int]) async -> [String] {
// withTaskGroup β guruhni yaratish
await withTaskGroup(of: String.self) { guruh in
// Har bir ID uchun parallel vazifa qo'shish
for id in idlar {
guruh.addTask {
// Har bir vazifa mustaqil ishlaydi
return await rasmYukla(id: id)
}
}
// Natijalarni yig'ish
var natijalar: [String] = []
for await natija in guruh {
natijalar.append(natija)
}
return natijalar
}
}
func rasmYukla(id: Int) async -> String {
try? await Task.sleep(for: .seconds(1))
return "Rasm #\(id)"
}
// Ishlatish
Task {
let rasmlar = await rasmlarniYukla(idlar: [1, 2, 3, 4, 5])
// 5 ta rasm PARALLEL yuklandi β ~1 soniya (ketma-ket bo'lsa 5 soniya)
print(rasmlar)
}
// βββββββββββββββββββββββββββββββββββββββ
// THROWING TASK GROUP β xato bilan
// βββββββββββββββββββββββββββββββββββββββ
func malumotnlarniYukla(urllar: [String]) async throws -> [Data] {
try await withThrowingTaskGroup(of: Data.self) { guruh in
for url in urllar {
guruh.addTask {
// Xato tashlashi mumkin
let (data, _) = try await URLSession.shared.data(
from: URL(string: url)!
)
return data
}
}
var natijalar: [Data] = []
// Bitta vazifa xato tashlasa β qolganlar bekor qilinadi
for try await data in guruh {
natijalar.append(data)
}
return natijalar
}
}
Task Priority β ustuvorlik
Har bir vazifaga ustuvorlik darajasi berilishi mumkin. Tizim ustuvorligi yuqori vazifalarni birinchi bajaradi. .high β tez javob kerak bo'lganda, .background β foydalanuvchi kutmaydigan fon ishlari uchun ishlatiladi. Default holat β .medium.
// Turli ustuvorlik darajalari
Task(priority: .high) {
// Muhim vazifa β tezroq bajariladi
await muhimIsh()
}
Task(priority: .background) {
// Kam muhim β fon da bajariladi
await fonIshi()
}
// Ustuvorlik darajalari:
// .high β muhim, tez bajarilishi kerak
// .medium β oddiy (default)
// .low β kam muhim
// .background β fon ishi, foydalanuvchi kutmaydi
// .utility β uzoq davom etadigan ish
// .userInitiated β foydalanuvchi boshlagan
π― Topshiriq
5 ta URL dan ma'lumot yuklaydigan TaskGroup yarating. Har bir vazifa natijasini for await bilan yig'ing. Bekor qilish mehanizmini qo'shing β 3 soniyadan keyin cancel() chaqiring va isCancelled tekshiring.