介绍
自 Objective-C 时代以来一直支持我们的 DispatchQueue 即将随着 Swift Concurrency (async/await) 的出现而结束其角色。
本文展示了如何将 Task
替换为 Task
用于使用 DispatchQueue
的各种用例。
笔记
- 基本上你不需要在iOS 13.0+中使用
DispatchQueue
-
请让我知道是否有一个只能用
DispatchQueue
实现的过程-
DispatchQueue
的优点是更容易调试,因为你可以命名队列
-
-
请让我知道是否有一个只能用
- 我没有检查之前/之后的处理是否完全相同
环境
- 操作系统:macOS 蒙特雷 12.5.1
- Xcode: 14.0 (14A309)
- 斯威夫特:5.7
更换清单
DispatchQueue
→ Task
替换列表。
调度队列 | 任务 |
---|---|
DispatchQueue.main.sync(excute:) |
MainActor.run(resultType:body:) |
DispatchQueue.main.async(excute:) |
Task.detached { @MainActor in ... } |
DispatchQueue.async(group:) |
async let |
DispatchQueue.main.asyncAfter(deadline:execute:) |
iOS 13.0+:Task.sleep(nanoseconds:) iOS 16.0+: Task.sleep(for:)
|
我敢肯定还有其他方法可以替换它。这里有一些简单的写作方法。
用例
我将按用例介绍替换。
等待特定过程完成
等待特定过程完成的用例。
直到现在我使用DispatchQueue.main.sync(excute:)
,但现在我使用MainActor.run(resultType:body:)
。
在下面的示例中,Before 和 After 都按照 1
→ 2
的顺序输出。
// Before
DispatchQueue.main.sync {
print("1")
}
print("2")
// After
Task {
await MainActor.run {
print("1")
}
print("2")
}
但是DispatchQueue.main.sync(excute:)
在主线程执行时会因为死锁而崩溃,所以基本上不应该使用它,所以这个用例的替代品可能不多。
异步执行特定处理
这是一个异步执行特定处理的用例。
到目前为止,我使用的是DispatchQueue.main.async(excute:)
,但从现在开始,我将使用Task.detached { @MainActor in ... }
。
这个替换是写在 Swift 提案中的。
在下面的示例中,Before 和 After 都以 2
→ 1
的顺序输出。
// Before
DispatchQueue.main.async {
print("1")
}
print("2")
// After
Task.detached { @MainActor in
print("1")
}
print("2")
如果不需要分离任务,可以写Task { @MainActor in ... }
。
如果您只是希望闭包中的处理在主线程上运行,我认为最好不要使用 Task.detached
。
// このように書くことのほうが多い
- Task.detached { @MainActor in
+ Task { @MainActor in
print("1")
}
print("2")
异步执行多个操作并等待它们完成
异步执行多个操作并等待它们完成的用例。
到目前为止,我使用的是DispatchQueue.async(group:)
,但现在我使用的是async let
。
即使没有异步方法返回值,也可以通过显式指定 Void
和 async let
将其分配为变量。
// Before
let group = DispatchGroup()
let queue1 = DispatchQueue(label: "com.example.myqueue1")
let queue2 = DispatchQueue(label: "com.example.myqueue2")
let queue3 = DispatchQueue(label: "com.example.myqueue3")
queue1.async(group: group) {
print("1")
}
queue2.async(group: group) {
print("2")
}
queue3.async(group: group) {
print("3")
}
group.notify(queue: .main) {
print("4")
}
// After
async let queue1: Void = printAsync("1")
async let queue2: Void = printAsync("2")
async let queue3: Void = printAsync("3")
_ = await (queue1, queue2, queue3)
print("4")
private func printAsync(_ text: String) async {
print(text)
}
延迟执行特定处理
这是一个延迟执行特定处理的用例。
到目前为止,我使用DispatchQueue.main.asyncAfter(deadline:execute:)
并将其作为闭包运行。
从现在开始,我们使用await Task.sleep(nanoseconds:)
来表示通过休眠来延迟执行。
但是,要指定的单位是纳秒,使用起来有点困难。
在 Xcode 14.1 (Swift 5.7.1) 和 iOS 16.0+ 中,您可以使用 Task.sleep(for:)
指定单位,因此最好使用它。
// Before
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) {
// ...
}
// After
Task {
// iOS 13.0+
try await Task.sleep(nanoseconds: 100_000_000)
// iOS 16.0+
try await Task.sleep(for: .nanoseconds(100_000_000))
try await Task.sleep(for: .microseconds(100_000))
try await Task.sleep(for: .milliseconds(100))
try await Task.sleep(for: .seconds(0.1))
// ...
}
综上所述
这将DispatchQueue
替换为Task
并且更智能
还有其他使用DispatchQueue
的用例,所以如果我得到评论,我想添加它们。
参考链接
- sync(execute:) | Apple 开发者文档
- async(execute:) | Apple 开发者文档
- run(resultType:body:) | Apple 开发者文档
- Swift Concurrency 总结(正式版已经支持)
- 使用 Swift 进行并发编程 - Qiita
- DispatchGroup | Apple 开发者文档
- init(label:qos:attributes:autoreleaseFrequency:target:) | Apple 开发者文档
- async(group:execute:) | Apple 开发者文档
- notify(queue:work:) | Apple 开发者文档
- asyncAfter(deadline:execute:) | Apple 开发者文档
- sleep(nanoseconds:) | Apple 开发者文档
- sleep(for:) | Apple 开发者文档
- 时长 | Apple 开发者文档
- https://twitter.com/the_uhooi/status/1531195527001350144
原创声明:本文系作者授权爱码网发表,未经许可,不得转载;
原文地址:https://www.likecs.com/show-308627623.html