Swift 并發任務的協作式取消

在 Swift 并發(Swift Concurrency)中,任務(Task)不會被強行終止,而是采用**協作式取消(cooperative cancellation)**機制。這意味著任務會被標記為“已取消”,但是否真正停止執行,取決于任務本身的邏輯處理。

本文將深入探討任務取消的原理、如何正確使用它,以及如何編寫高效的 Swift 并發代碼。

一 ?什么是協作式取消?

協作式取消的核心思想是:調用方不能直接終止任務,而只能標記它為取消。任務本身需要定期檢查這個標記,并決定要不要提前終止。

Swift 并不會強制中止任務,而是給你一個信號,告訴你“這個任務已經沒用了,你要不要停下來?”你可以選擇:

  • 直接返回

  • 提供部分結果

  • 繼續執行(如果業務邏輯需要)

二 ?任務取消的基本用法

來看一個 SwiftUI 代碼示例。當用戶輸入搜索內容時,會觸發異步搜索。

struct ContentView: View {@State private var store = Store()@State private var query = ""var body: some View {NavigationView {List(store.results, id: \ .self) { result inText(result)}.searchable(text: $query).task(id: query) {await store.search(matching: query)}}}
}

task(id: query)?處理任務取消

這一行代碼的作用是:

  1. 當?query?變化時,SwiftUI?啟動一個新的搜索任務

  2. SwiftUI 會標記前一個任務為“已取消”,但不會立即終止它。

如果舊任務沒有檢查取消狀態,它可能仍然會繼續執行。這可能導致多個任務同時運行,影響性能。因此,我們需要手動處理任務取消。

三 ?在異步方法中正確處理取消

假設?Store?負責執行搜索查詢,我們的?search(matching:)?方法可能如下:

@MainActor
final class Store: ObservableObject {@Published private(set) var results: [String] = []func search(matching query: String) async {do {let fetchedResults = await fetchData(query: query)try Task.checkCancellation() // 檢查任務是否已取消results = fetchedResults} catch {results = []}}
}

Task.checkCancellation()

  • 這個方法會拋出一個錯誤。

  • 如果任務已被取消,它會立刻終止,后續代碼不會執行。

  • 這樣可以避免執行無用的邏輯,比如過濾數據或更新 UI。

四 ?在多個步驟中檢查任務取消

如果異步任務包含多個步驟,比如先獲取數據,再處理數據,建議在多個關鍵點檢查取消狀態。

@MainActor
final class Store: ObservableObject {@Published private(set) var results: [String] = []func search(matching query: String) async {do {let rawData = await fetchRawData(query: query)try Task.checkCancellation() // 第一次檢查let processedData = processData(rawData)try Task.checkCancellation() // 第二次檢查results = processedData} catch {results = []}}
}

為什么要多次檢查?

如果?fetchRawData?執行了一段時間,任務在這期間被取消,我們希望盡早停下來,而不是等整個任務執行完。

五 ?用?Task.isCancelled?進行檢查

除了?Task.checkCancellation(),Swift 還提供了?Task.isCancelled?這個屬性。

actor SearchService {private var cachedResults: [String] = []func search(matching query: String) async -> [String] {guard !Task.isCancelled else {return cachedResults // 任務取消,直接返回緩存數據}let rawData = await fetchData(query: query)guard !Task.isCancelled else {return cachedResults // 避免不必要的計算}let filteredData = processData(rawData)cachedResults = filteredDatareturn filteredData}
}

Task.isCancelled?vs?Task.checkCancellation()

方法作用
Task.checkCancellation()拋出錯誤,任務立即終止
Task.isCancelled返回?true/false,可以手動決定是否終止

六 ?手動取消任務

Swift 允許你手動創建任務并取消它。

struct ExampleView: View {@State private var store = Store()@State private var task: Task<Void, Never>?var body: some View {VStack {Button("開始任務") {task = Task {await store.search(matching: "Apple")}}Button("取消任務") {task?.cancel()}}}
}

task?.cancel()?只會標記任務為取消,但不會真正終止它。因此,你仍然需要在?search(matching:)?里檢查?Task.isCancelled?或?Task.checkCancellation()

七 ?結論

  1. Swift?不會自動終止任務,只會標記它為取消。

  2. 用?Task.checkCancellation()?可以立即終止任務,防止執行不必要的邏輯。

  3. 用?Task.isCancelled?可以更靈活地處理任務取消

  4. 如果任務有多個異步步驟,應該在關鍵點多次檢查取消狀態

  5. 手動創建的任務需要手動取消,但仍然需要在任務內部檢查取消狀態。

這樣,你就能寫出高效、優雅的 Swift 并發代碼,避免不必要的計算,提高用戶體驗!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/74112.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/74112.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/74112.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

大數據(1.1)紐約出租車大數據分析實戰:從Hadoop到Azkaban的全鏈路解析與優化

目錄 一、背景與數據價值? ?二、技術選型與組件分工? ?三、數據準備與預處理? 四、實戰步驟詳解? ?1. 數據上傳至HDFS ?2. Hive數據建模與清洗? 4?.2.1 建表語句&#xff08;分區表按年份&#xff09;?&#xff1a; ?4?.2.2 數據清洗&#xff08;剔除無效…

代碼隨想錄刷題day50|(回溯算法篇)131.分割回文串▲

目錄 一、回溯算法基礎知識 二、分割回文串思路 2.1 如何切割 2.2 判斷回文 2.3 回溯三部曲 2.4 其他問題 三、相關算法題目 四、總結 一、回溯算法基礎知識 詳見&#xff1a;代碼隨想錄刷題day46|&#xff08;回溯算法篇&#xff09;77.組合-CSDN博客 二、分割回文…

VS Code PowerShell、Windows PowerShell、CMD 的區別與聯系

VS Code PowerShell、Windows PowerShell、CMD 的區別與聯系? VS Code PowerShell、Windows PowerShell、CMD 的區別與聯系&#xff1a; 一、核心概念對比 名稱 全稱 類型 定位 VS Code PowerShell Visual Studio Code PowerShell 代碼編輯器集成終端 開發/腳本編寫…

關于Unity的CanvasRenderer報錯

MissingReferenceException: The object of type ‘CanvasRenderer’ has been destroyed but you are still trying to access it. Your script should either check if it is null or you should not destroy the object. UnityEngine.UI.GraphicRaycaster.Raycast (UnityEng…

C++編譯流程

編譯器其實就是一個翻譯器&#xff0c;把我們的文件內容翻譯成機器能夠看懂的指令&#xff0c;但如何合理翻譯是核心。 C語言編譯 需要經過以下幾步&#xff1a; 詞法分析&#xff1a;掃描代碼&#xff0c;確定單詞類型&#xff0c;比如是變量還是函數&#xff0c;是標識符還…

python學智能算法(八)|決策樹

【1】引言 前序學習進程中&#xff0c;已經對KNN鄰近算法有了探索&#xff0c;相關文章鏈接為&#xff1a; python學智能算法&#xff08;七&#xff09;|KNN鄰近算法-CSDN博客 但KNN鄰近算法有一個特點是&#xff1a;它在分類的時候&#xff0c;不能知曉每個類別內事物的具…

使用 OpenCV 拼接進行圖像處理對比:以形態學操作為例

圖像處理在計算機視覺中起著至關重要的作用&#xff0c;而 OpenCV 作為一個強大的圖像處理庫&#xff0c;提供了豐富的函數來實現各類圖像處理任務。形態學操作&#xff08;Morphological Operations&#xff09;是其中常用的技術&#xff0c;尤其適用于二值圖像的處理。常見的…

版本控制器Git ,Gitee如何連接Linux Gitee和Github區別

&#x1f4d6; 示例場景 假設你和朋友在開發一個「在線筆記網站」&#xff0c;代碼需要頻繁修改和協作&#xff1a; 只用本地文件管理 每次修改后手動復制文件&#xff0c;命名為 v1.html、v2.html 問題&#xff1a;無法追蹤具體改動內容&#xff1b;多人修改易沖突&#xff1…

使用DeepSeek翻譯英文科技論文,以MarkDown格式輸出,使用Writage 3.3.1插件轉換為Word文件

一、使用DeepSeek翻譯英文科技論文&#xff0c;以MarkDown格式輸出 以科技論文“Electrical Power System Sizing within the Numerical Propulsion System Simulation”為例。 關于Writage 3.3.1的進一步了解&#xff0c;可發送郵件至郵箱pyengine163.com. 首先&#xff0c;打…

【NPU 系列專欄 3.0 -- scale-out 和 scale-in 和 scale-up 和 scale-down

文章目錄 Overview1. Scale-out 和 Scale-in (橫向擴展/縮減)舉例:AI SoC 中的 Scale-out 和 Scale-in2. Scale-up 和 Scale-down (縱向擴展/縮減)舉例:AI SoC 中的 Scale-up 和 Scale-down對比總結Overview 本文會 以 AI SoC 為例 詳細介紹什么是 scale-out 和 scale-i…

Spring Boot 集成 Quartz 實現定時任務(Cron 表達式示例)

Spring Boot 集成 Quartz 實現定時任務&#xff08;Cron 表達式示例&#xff09; 前言1. 添加 Quartz 依賴2. 創建 Quartz 任務3. 配置 Quartz 任務調度4. 啟動 Spring Boot 觀察定時任務執行5. Quartz Cron 表達式詳解6. 結論 前言 在 Spring Boot 項目中&#xff0c;我們經常…

智能汽車圖像及視頻處理方案,支持視頻智能拍攝能力

美攝科技&#xff0c;作為智能汽車圖像及視頻處理領域的先行者&#xff0c;憑借其卓越的技術實力和前瞻性的設計理念&#xff0c;為全球智能汽車制造商帶來了一場視覺盛宴的革新。我們自豪地推出——美攝科技智能汽車圖像及視頻處理方案&#xff0c;一個集高效性、智能化、畫質…

QPrintDialog彈出慢的問題

開發環境 操作系統: openkylin2qt版本 : 5.15.10排查過程 首先看下問題的現象, 問題現象 復現問題的demo很簡單,只能是從跟蹤qt代碼方面入手 void MainWindow::on_pushButton_clicked(){QPrinter printer;QPrintDialog dialog(&printer,this);dialog.exec();} 現在需要找一…

VLAN:邏輯隔離沖突網絡的詳細講解

1. VLAN的基本概念 VLAN&#xff08;Virtual Local Area Network&#xff0c;虛擬局域網&#xff09; 是一種將物理網絡劃分為多個邏輯獨立網絡的技術。通過VLAN&#xff0c;不同邏輯網絡可以在同一物理網絡基礎設施上運行&#xff0c;彼此隔離&#xff0c;互不影響。 核心功能…

投影算子(Projection Operator)的定義、性質、分類以及應用

文章目錄 1. 投影算子的定義2. 投影算子的幾何意義3. 一些簡單的例子例 1&#xff1a;二維平面上的投影例 2&#xff1a;投影到一條任意方向的直線例 3&#xff1a;三維空間中投影到一個平面 4. 投影算子的性質4.1、冪等性&#xff08;Idempotency&#xff09;&#xff1a; P 2…

java使用Apache POI 操作word文檔

項目背景&#xff1a; 當我們對一些word文檔&#xff08;該文檔包含很多的標題比如 1.1 &#xff0c;1.2 &#xff0c; 1.2.1.1&#xff0c; 1.2.2.3&#xff09;當我們刪除其中一項或者幾項時&#xff0c;需要手動的對后續的進行補充。該功能主要是對標題進行自動的補充。 具…

接收與發送ipv6數據包

一、ipv6的概念 IPv6 是英文 “Internet Protocol Version 6”&#xff08;互聯網協議第 6 版&#xff09;的縮寫&#xff0c;是互聯網工程任務組&#xff08;IETF&#xff09;設計的用于替代 IPv4 的下一代 IP 協議&#xff0c;其地址數量號稱可以為全世界的每一粒沙子編上…

龍虎榜——20250321

今日A股龍虎榜方向分析 根據2025年3月21日龍虎榜數據&#xff08;漲停56家&#xff0c;跌停31家&#xff09;&#xff0c;市場呈現結構性分化行情&#xff0c;資金聚焦海洋經濟、機器人、鋰電等主線&#xff0c;部分個股遭機構大幅拋售。以下是具體方向解析&#xff1a; 一、資…

springboot milvus search向量相似度查詢 踩坑使用經驗

1.前提提要&#xff1a;java的pom 版本為&#xff1a;2.4.9 milvus 版本是&#xff1a;2.4.13-hotfix 2.先來工具類方法 /*** 向量搜索* param client* param query* return*/public SearchResp search(NonNull MilvusClientV2 client, NonNull VectorCondition query) {final …

[網絡安全] 濫用Azure內置Contributor角色橫向移動至Azure VM

本文來源于團隊的超輝老師&#xff0c;其系統分析了Azure RBAC角色模型及其在權限濫用場景下的攻擊路徑。通過利用AADInternals工具提升用戶至Contributor角色&#xff0c;攻擊者可在Azure VM中遠程執行命令&#xff0c;創建后門賬戶&#xff0c;實現橫向移動。文中詳述了攻擊步…