Published on

Swiftda Task va TaskGroup

Authors

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.

Buy mea coffee