如何在Swift同步函数中调用异步函数并阻塞获取结果?
在Swift同步函数中阻塞调用Async函数并获取结果
直接上简洁可行的实现,结合Task和DispatchSemaphore解决返回值与阻塞的问题:
func syncWrapperForAsync<T>(_ asyncOperation: @escaping () async throws -> T) throws -> T { var operationResult: Result<T, Error>? let semaphore = DispatchSemaphore(value: 0) // 启动异步任务 Task { do { let output = try await asyncOperation() operationResult = .success(output) } catch { operationResult = .failure(error) } // 任务完成后发送信号,解除阻塞 semaphore.signal() } // 阻塞当前线程,等待异步任务完成 semaphore.wait() // 取出结果并返回,若有错误则抛出 return try operationResult!.get() }
为什么这个方案能解决你的问题?
- 针对你尝试的方法1:补上了
DispatchSemaphore实现阻塞,同时用Result存储异步任务的返回值/错误,解决了“无法获取结果且不阻塞”的问题 - 针对你尝试的方法2:通过
Result类型捕获异步执行的结果,解决了“无法获取返回值”的问题 - 对比方法3的EventLoop Promise:这个实现更轻量,不需要依赖EventLoop相关的API,代码逻辑更直观
使用示例
假设你有一个异步函数:
func asyncFetchData() async throws -> String { await Task.sleep(1_000_000_000) // 模拟1秒的耗时操作 return "Async Operation Completed" }
在同步函数中调用:
func mySyncFunction() { do { let result = try syncWrapperForAsync(asyncFetchData) print("Result: \(result)") } catch { print("Error occurred: \(error)") } }
注意事项
- 避免在主线程中使用这种方式:如果异步任务需要在主线程执行,而主线程被
semaphore.wait()阻塞,会直接导致死锁。确保异步任务的执行线程与当前阻塞线程不冲突。 - 尽量减少这种混合调用:async/await的设计初衷是让异步代码更流畅,同步阻塞调用异步函数是妥协方案,仅用于兼容旧的同步代码架构。
内容的提问来源于stack exchange,提问作者Anton
相关产品推荐
相关产品推荐

