提问人:e987 提问时间:5/4/2023 更新时间:5/5/2023 访问量:157
为什么我不能将 Concurrency 导入到我的 Swift 5.8 项目中?
Why can I not import Concurrency into my Swift 5.8 project?
问:
我正在尝试编译这个简单的示例,首先Xcode 14.3(Swift 5.8)告诉我
No such module 'Concurrency'
然后,如果我将该行更改为导入_Concurrency,Xcode 14.3 会告诉我
Cannot find 'withTimeout' in scope
使用'withDeadline()'也是如此。怎么了?
import Foundation
import Concurrency
func fetchImageData() async throws -> Data {
return try await withTimeout(1) {
// Simulate a long-running async operation
let imageData = try await URLSession.shared.data(from: URL(string: "https://example.com/image.jpg")!)
return imageData.0
}
}
答:
1赞
Rob
5/5/2023
#1
Swift 并发不需要任何内容,因为它是为您导入的。import
但是没有功能。不过,你可以写一个。也许:withTimeout
extension Task where Failure == Error {
/// Run asynchronous task, but cancel it if not finished within a certain period of time.
///
/// - Parameters:
/// - duration: The duration before the task is canceled.
/// - operation: The async closure to run. The code therein should support cancelation.
/// - Throws: If canceled, will throw `CancellationError`. If the task fails, this will throw the task’s error.
/// - Returns: This will return the value returned by the `async` closure.
static func withTimeout(_ duration: Duration, operation: @Sendable @escaping () async throws -> Success) async rethrows -> Success {
let operationTask = Task.detached {
try await operation()
}
let cancelationTask = Task<Void, Error>.detached {
try await Task<Never, Never>.sleep(for: duration)
operationTask.cancel()
}
return try await withTaskCancellationHandler {
defer { cancelationTask.cancel() }
return try await operationTask.value
} onCancel: {
operationTask.cancel()
}
}
}
毋庸置疑,我用更通用的 (即秒) 替换了 (即秒),并使其成为 的方法,但总体思路很简单:基本上,为提供的闭包启动一个任务,为取消另一个任务启动另一个任务,谁先完成将取消另一个任务。显然,如果 本身被取消,那么取消非结构化并发任务也是如此。TimeInterval
Duration
static
Task
withTimeout
但不要迷失在这一点上的杂草中,因为人们可能会考虑这个主题有很多变化。
那么你可以这样称呼它:
func fetchImageData(from url: URL) async throws -> Data {
try await Task.withTimeout(.seconds(1)) {
try await URLSession.shared.data(from: url).0
}
}
综上所述,/两者都已经有一个超时参数,所以你不妨使用它,也许:URLSession
URLRequest
nonisolated func fetchImageData(from url: URL) async throws -> Data {
let request = URLRequest(url: url, timeoutInterval: 1)
return try await URLSession.shared.data(for: request).0
}
评论
0赞
Itai Ferber
5/5/2023
这个版本太棒了;不过,我会考虑更突出地记录,如果不支持取消(无论是故意的,还是因为它只是不知道取消),超时将不适用。这可能非常微妙且有些危险,因此值得注意。在代码审查中,我什至建议将方法重命名为类似的东西,以便在调用站点上更明确(尽管我知道您只是使用帖子中介绍的名称。withTimeout
operation
performCancellableWithTimeout(_:_:)
0赞
Rob
5/6/2023
在我的辩护中,我确实试图在文档中提到取消(这是这个一次性代码片段包含内联文档的唯一原因)。但我听到你说,这当然可以使它更加突出。
1赞
Itai Ferber
5/6/2023
哦,是的!不是为了批评(很高兴地投了赞成票!)——我只是通常非常厌恶这种事情的风险,所以对于任何将其集成到他们的代码库中的人来说,这是一个小建议。
评论
Concurrency
_Concurrency
withTimeout
withDeadline
Task
async
await