假设我有一个异步函数:
func doAsyncWork() async throws { ... }
该函数可以从多个地方调用。我想要实现的是确保该函数永远不会同时执行多次。例如,如果有人在第一个调用者仍在执行该函数时调用该函数,则它应该将第二个调用排队,直到第一个调用完成(依此类推,并进行适当的错误传播)。必须保留调用的顺序,因此可能需要诸如 FIFO 队列之类的东西来存储尚未处理的调用。
我想避免仅出于此目的使用 RxSwift 等外部库/框架,因此我正在寻找一个普通的 Swift 解决方案。有什么想法吗?
我与 ChatGPT“讨论”了我的问题,我们最终得到了这样的效果,效果很好(但也许有更好的解决方案):
import Foundation
class SerializedFunctionCaller {
private let serialQueue = DispatchQueue(label: "com.yourapp.serializedFunctionQueue")
// Define a generic async function that can throw an error
func callAsyncFunction<T>(_ function: @escaping () async throws -> T) async throws -> T {
return try await withCheckedThrowingContinuation { continuation in
// Use a serial queue for serialized access
serialQueue.async {
Task {
do {
// Call the async function and pass the result to the continuation
let result = try await function()
continuation.resume(returning: result)
} catch {
// If an error occurs, pass the error to the continuation
continuation.resume(throwing: error)
}
}
}
}
}
}
// Example usage:
let serializedCaller = SerializedFunctionCaller()
// Define your async function
func yourAsyncFunction() async throws {
// Your async work here
print("Function started at \(Date())")
try await Task.sleep(nanoseconds: 1_000_000_000 * 1) // 1 sec
print("Function finished at \(Date())")
}
// Call the function from multiple places
Task {
do {
try await serializedCaller.callAsyncFunction(yourAsyncFunction)
try await serializedCaller.callAsyncFunction(yourAsyncFunction)
} catch {
print(error)
}
}