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.mzph.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;实现横向移动。文中详述了攻击步…