【问题标题】:'async' call in a function that does not support concurrency swift ios Xcode async/await在不支持并发的函数中调用'async' swift ios Xcode async/await
【发布时间】:2021-08-27 17:16:25
【问题描述】:

我正在尝试在 Swift 5.5 中使用 async/await。我有我的异步函数,但每当我尝试调用它时,我都会收到此错误:

在不支持并发的函数中调用'async'

这是代码示例:

class TryThis {
    func getSomethingLater(_ number: Double) async -> String {
        // test - sleep for 3 seconds, then return
        Thread.sleep(forTimeInterval: 3)
        return String(format: ">>>%8.2f<<<", number)
    }
}

let tryThis = TryThis()

let result = await tryThis.getSomethingLater(3.141592653589793238462)
print("result: \(result)")

解决办法是什么?

【问题讨论】:

    标签: ios swift xcode macos async-await


    【解决方案1】:

    这里的答案是“await getSomethingLater”必须从异步上下文中调用。从字面上看,这意味着改变这一点:

    let result = await tryThis.getSomethingLater(3.141592653589793238462)
    print("result: \(result)")
    

    进入这个:

    Task {
        let result = await tryThis.getSomethingLater(3.141592653589793238462)
        print("result: \(result)")
    }
    

    所以整个事情变成了:

    class TryThis {
        func getSomethingLater(_ number: Double) async -> String {
            // test - sleep for 3 seconds, then return
            Thread.sleep(forTimeInterval: 3)
            return String(format: ">>>%8.2f<<<", number)
        }
    }
    
    let tryThis = TryThis()
    
    Task {
        let result = await tryThis.getSomethingLater(3.141592653589793238462)
        print("result: \(result)")
    }
    

    这是输出:

    结果:>>> 3.14

    WWDC21 的 Meet sync/await in Swift 视频中有大量信息。

    【讨论】:

    • 我收到警告 'async(priority:operation:)' is deprecated: async` 已被 Task.init 替换,很快就会被删除。`。我认为这意味着不应再接受这个答案。
    【解决方案2】:

    产生原始错误是因为 Swift 尚不支持“顶级”等待(即全局范围内的代码)。 该错误只是意味着您需要为 async 函数提供异步上下文,例如使用 TaskTask.detachedTaskGroup,具体取决于您想要的行为。

    Task.detached {
        let result = await tryThis.getSomethingLater(3.141592653589793238462)
        print("result: \(result)")
    }
    

    但是,当最终提出、实施和支持顶级 await 时,您的代码 sn-p 应该可以工作。 作为 async/await SE-0296 的原始提案的一部分,提到了顶级等待支持。

    【讨论】:

      【解决方案3】:

      当从非async 代码调用async 代码(包括actor 字段)时,您必须将其包装在Task 中:

      Task {
          let result = await tryThis.getSomethingLater(3.141592653589793238462)
          print("result: \(result)")
      }
      

      延伸阅读:Concurrency — The Swift Programming Language (Swift 5.5)

      【讨论】:

        猜你喜欢
        • 2023-01-02
        • 2017-12-17
        • 2019-02-17
        • 2021-08-06
        • 1970-01-01
        • 2021-10-15
        相关资源
        最近更新 更多