You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中不修改foo1(),如何让foo2()在foo1()之后执行?

问题解决:不修改foo1()让输出2在1之后

当前代码中,foo1()内部启动了一个异步Task,会在1秒后打印"1";而foo2()会被立即调用打印"2",默认输出顺序是2→1。由于要求不能修改foo1(),可以通过以下两种方式调整执行顺序:

1. 不可靠的固定等待(适合练习理解)

这种方式通过在调用foo2()前等待足够长的时间,确保foo1()内部的Task完成。优点是简单,缺点是不可靠——如果foo1()内部的Task执行时间变化,结果就会出错。

修改后的代码:

func foo1() {
    Task {
        try await Task.sleep(nanoseconds: 1_000_000_000)
        print("1")
    }
}

func foo2() {
    print("2")
}

func mainFunc() async {
    foo1()
    // 等待foo1的Task执行完成,额外预留100ms避免误差
    try await Task.sleep(nanoseconds: 1_100_000_000)
    foo2()
}

// 启动异步的mainFunc
Task {
    await mainFunc()
}

2. 黑客式的Task追踪(仅用于学习探索,禁止生产环境使用)

由于foo1()没有暴露内部的Task引用,我们可以通过方法替换(Swizzling)来追踪所有创建的Task,然后等待foo1()启动的Task完成。这种方式会影响全局Task的行为,存在稳定性风险,仅适合学习Swift并发的底层机制。

修改后的代码:

import Foundation

extension Task where Success == Void, Failure == Never {
    private static let originalInit = Task.init(priority:operation:)
    static var trackedTasks: [Task] = []
    
    static func init(priority: TaskPriority? = nil, operation: @escaping @Sendable () async -> Void) -> Task {
        let task = originalInit(priority: priority, operation: operation)
        trackedTasks.append(task)
        return task
    }
}

func foo1() {
    Task {
        try await Task.sleep(nanoseconds: 1_000_000_000)
        print("1")
    }
}

func foo2() {
    print("2")
}

func mainFunc() async {
    let initialTaskCount = Task.trackedTasks.count
    foo1()
    
    // 等待foo1新启动的Task全部完成
    let newTasks = Task.trackedTasks.dropFirst(initialTaskCount)
    for task in newTasks {
        await task.value
    }
    
    foo2()
}

// 启动异步的mainFunc
Task {
    await mainFunc()
}

核心结论

如果foo1()不主动暴露内部的异步任务(比如返回Task实例或提供completion handler),没有可靠且安全的方式从外部强制同步执行它的内部Task。上述两种方式仅适合练习场景,生产环境必须让foo1()提供异步任务的引用才能实现可靠等待。

内容的提问来源于stack exchange,提问作者Bruno De Vivo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 13:33:12