成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Swift 并發中的 Yielding 和 Debouncing

開發 前端
本篇文章的主題是任務讓步(Task Yielding) 和 防抖(Debouncing)。Swift 并發為我們提供了兩個簡單但非常強大的函數:yield? 和 sleep。今天我們就來看看它們的用法,以及在什么場景下應該使用它們。

前言 

本篇文章的主題是 任務讓步(Task Yielding) 和 防抖(Debouncing)。Swift 并發為我們提供了兩個簡單但非常強大的函數:yield 和 sleep。今天我們就來看看它們的用法,以及在什么場景下應該使用它們。

什么是任務防抖(Debouncing)? 

想象一下,你正在開發一個搜索功能,用戶每輸入一個字符,程序就會去一個龐大的數據集里查找匹配的結果。如果不加控制,每次鍵入都會觸發新的搜索任務,可能會導致多個任務同時執行,影響性能甚至引發競爭條件(Race Condition)。

比如,下面這個 SwiftUI 代碼:

@MainActor @Observablefinalclass Store {
    private(set) var results: [HKCorrelation] = []
    privatelet store = HKHealthStore()

    func search(matching query: String) async {
        // 執行復雜的搜索任務
    }
}

struct ContentView: View {
    @Stateprivatevar store = Store()
    @Stateprivatevar query = ""

    var body: some View {
        NavigationStack {
            List(store.results, id: \.uuid) { result in
                Text(verbatim: result.endDate.formatted())
            }
            .searchable(text: $query)
            .task(id: query) {
                await store.search(matching: query)
            }
        }
    }
}

在這個代碼里,每次用戶輸入新字符,都會創建一個新的任務去執行搜索。而 Swift 并發采用 協作式取消機制(Cooperative Cancellation),也就是說,它不會直接強行終止任務,而是提供一個“取消標記”,任務需要自己檢查并響應取消請求。因此,這種寫法可能會導致多個搜索任務并行運行,消耗不必要的計算資源。

為了解決這個問題,我們可以用 防抖(Debouncing) 技術。

如何用 sleep 實現防抖? 

防抖的思路很簡單:

  • 戶輸入時,我們 等待一小段時間,看看用戶是否繼續輸入。
  • 如果輸入仍然在變化,我們就 繼續等待,而不是立即啟動搜索。
  • 只有當輸入 穩定 一定時間后,才觸發搜索任務

換句話說,如果用戶輸入 "apple",我們希望忽略 "a", "ap", "app", "appl",只在最終輸入 "apple" 后再進行搜索。

在 Swift 并發中,我們可以用 Task.sleep 來實現這個效果:

struct ContentView: View {
    @Stateprivatevar store = Store()
    @Stateprivatevar query = ""

    var body: some View {
        NavigationStack {
            List(store.results, id: \.uuid) { result in
                Text(verbatim: result.endDate.formatted())
            }
            .searchable(text: $query)
            .task(id: query) {
                do {
                    try await Task.sleep(for: .seconds(1))  // 等待 1 秒
                    await store.search(matching: query)  // 執行搜索
                } catch {
                    // 任務可能因為新輸入被取消
                }
            }
        }
    }
}

為什么這樣就能實現防抖?

  • Task.sleep(for: .seconds(1)) 讓當前任務暫停 1 秒。
  • 如果用戶在 1 秒內繼續輸入,之前的任務會被取消,新任務重新計時。
  • 只有 用戶停止輸入超過 1 秒,才會觸發真正的搜索任務。

效果: 這樣可以避免在輸入過程中反復觸發搜索,減少不必要的計算量。

什么是任務讓步(Task Yielding)? 

除了防抖,Swift 并發還提供了 任務讓步(Task Yielding),讓你在執行長時間任務時,主動把線程讓出來,讓其他任務有機會運行。

想象一個場景:

你需要解析一批巨大的 JSON 文件,并將數據保存到磁盤。這個過程可能會運行很久,占用線程資源。如果你在主線程或并發線程池(Cooperative Thread Pool)上運行這種任務,會 阻塞其他任務的執行,導致性能問題。

比如,下面是一個解析 JSON 文件的代碼:

struct Item: Decodable {
    // 解析 JSON 的結構
}

struct DataHandler {
    func process(json files: [Data]) async throws -> [Item] {
        let decoder = JSONDecoder()
        var result: [Item] = []

        for file in files {
            let items = try decoder.decode([Item].self, from: file)
            result.append(contentsOf: items)
        }

        return result
    }
}

這個 process 函數會遍歷所有 JSON 文件,并解析它們。但問題是:

  • 解析 JSON 是一個 同步操作,它不會自動釋放 CPU 資源。
  • 如果 JSON 文件很大,整個解析過程可能會 占用線程很長時間,導致其他任務被阻塞。

如何用 yield 讓出線程? 

為了解決這個問題,我們可以 在每次解析完一個 JSON 文件后,讓出線程,讓其他任務有機會執行:

struct DataHandler {
    func process(json files: [Data]) async throws -> [Item] {
        let decoder = JSONDecoder()
        var result: [Item] = []

        for file in files {
            let items = try decoder.decode([Item].self, from: file)
            result.append(contentsOf: items)

            await Task.yield()  // 讓出線程,讓其他任務有機會執行
        }

        return result
    }
}

任務讓步的好處:

  • await Task.yield() 會讓當前任務 暫停一下,讓其他等待中的任務有機會執行。
  • 之后,系統會恢復這個任務的執行,繼續處理下一個 JSON 文件。
  • 這樣可以 更公平地分配 CPU 資源,防止某個任務獨占線程。

什么時候需要 yield? 

通常來說,如果你的代碼已經是 異步的(async/await),系統會自動在 await 語句處讓出線程。所以 **大部分情況下,你不需要手動 yield**。

但是,當你處理 非異步 API(比如 JSON 解析、圖片處理、大量計算等)時,手動 yield 可能會提升性能。

總結 

  • 防抖(Debouncing)

a.適用于 用戶頻繁輸入的場景,如搜索框、按鈕點擊等。

b.通過 Task.sleep(for:) 實現,等輸入穩定后再執行任務。

c.避免頻繁創建任務,提高性能。

  • 任務讓步(Task Yielding)

      a.適用于 長時間運行的計算密集型任務,如解析 JSON、圖片處理等。

      b.通過 Task.yield() 讓出 CPU,避免線程被長時間占用。

      c.讓其他任務有機會執行,提高系統響應速度。

這兩個技巧雖然簡單,但在實際開發中非常有用,可以幫助你更高效地利用 Swift 并發,讓你的應用運行得更流暢!

責任編輯:姜華 來源: Swift社區
相關推薦

2025-03-21 09:01:34

Swift任務取消機制協作式取消

2022-04-06 09:10:03

抽象類型普通類型Swift

2023-11-03 11:56:34

2015-01-21 16:25:29

Swift指針

2015-03-16 10:33:14

Swift指針

2015-07-08 16:43:02

Configurati

2015-11-23 10:07:19

Swift模式匹配

2021-11-10 15:18:16

JavaGo命令

2022-04-26 08:41:38

Swift并發系統iOS

2023-11-20 22:44:09

Golang并發

2021-12-22 15:13:03

iOS 15Swift二進制

2022-05-11 09:01:54

Swift類型系統幻象類型

2022-07-04 08:54:39

Swift處理器項目

2020-11-12 19:15:54

Swift蘋果開發

2021-07-07 11:41:38

Swift key paths

2022-05-25 09:15:01

Swift 5.6占位符

2022-06-13 09:02:06

Swift類型占位符

2023-03-27 09:57:00

PostgreSQL并發索引

2025-05-22 09:01:28

2024-08-26 09:51:57

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日韩中文字幕在线视频观看 | 91热爆在线观看 | 精品国产乱码久久久久久图片 | 久久久久久久久99精品 | 精国产品一区二区三区四季综 | 久久伊人精品 | 精品一区二区三区在线观看 | 日本在线观看网址 | 国产一区二区三区在线看 | 久久成人久久 | 亚洲精品一区二区二区 | 狠狠撸在线视频 | 99精品在线观看 | 日韩一区二区三区视频在线播放 | 国产成人免费网站 | 久久久.com| 国产成人在线视频播放 | 色呦呦网站 | 色黄视频在线 | 成人精品在线观看 | 色爽女 | 免费av播放| 欧美大片一区 | 久久久新视频 | 日韩精品激情 | 一区二区三区视频播放 | 免费a大片 | 涩涩导航 | 日本天天操 | 中文字幕日韩欧美一区二区三区 | 黄色大片免费网站 | 久久久久久综合 | 美女爽到呻吟久久久久 | 国产午夜久久久 | 天天操天天射天天 | 97精品超碰一区二区三区 | 久久久久亚洲国产| 久久久婷婷| 99精品国产一区二区青青牛奶 | 国产av毛片 | 日日夜夜精品免费视频 |