@MainActor 闭包似乎没有确定地在主线程上执行

问题描述 投票:0回答:2

考虑以下相对简单的 Swift 程序:

import Foundation

func printContext(function: String = #function, line: Int = #line) {
    print("At \(function):\(line): Running on \(Thread.current) (main: \(Thread.isMainThread))")
}

printContext()

Task { @MainActor in
    printContext()
}

Task.detached { @MainActor in
    printContext()
}

Task {
    await MainActor.run {
        printContext()
    }
}

DispatchQueue.main.async {
    printContext()
}

dispatchMain()

根据全球参与者提案,我预计

DispatchQueue.main.async { ...
大致相当于
Task.detached { @MainActor in ...

然而,在

arm64-apple-macosx12.0
上的 Swift 5.6.1 中,该程序似乎在调用时不确定地产生不同的结果。有时我会得到预期的输出:

At main:7: Running on <_NSMainThread: 0x600000083c80>{number = 1, name = main} (main: true)
At main:10: Running on <_NSMainThread: 0x600000083c80>{number = 1, name = main} (main: true)
At main:19: Running on <_NSMainThread: 0x600000083c80>{number = 1, name = main} (main: true)
At main:14: Running on <_NSMainThread: 0x600000083c80>{number = 1, name = main} (main: true)
At main:24: Running on <_NSMainThread: 0x600000083c80>{number = 1, name = main} (main: true)

有时,

@MainActor
闭包似乎在另一个线程上执行:

At main:7: Running on <_NSMainThread: 0x600002ae44c0>{number = 1, name = main} (main: true)
At main:24: Running on <_NSMainThread: 0x600002ae44c0>{number = 1, name = main} (main: true)
At main:10: Running on <NSThread: 0x600002afff00>{number = 2, name = (null)} (main: false)
At main:19: Running on <NSThread: 0x600002afff00>{number = 2, name = (null)} (main: false)
At main:14: Running on <NSThread: 0x600002afff00>{number = 2, name = (null)} (main: false)

只有

DispatchQueue
机制似乎可以可靠地调度到
main
线程上。我是否误解了并发模型的一部分,或者为什么程序会这样?

swift concurrency actor swift-concurrency
2个回答
0
投票

是的,async/await 抽象了线程。在幕后,有一个线程池,当您运行任务时,您基本上是说,当有可用时间(并给予优先级)时,运行此代码。您的代码可能会在一个线程上挂起,然后在同一任务中的另一个线程上恢复。

因此,任务中运行的代码可以在随机线程上运行。要在主线程上运行代码,您需要使用

await MainActor.run
。否则,你没有保证。


0
投票

全局参与者(包括主要参与者)进行了优化,如果部分任务不执行任何实际需要参与者隔离的操作,则它们可以消除不必要的执行器跳跃。最终效果是代码并不总是在您可能期望的线程上运行。

但是,如果您更改示例,使其明确要求参与者隔离(例如,可能增加与主要参与者隔离的计数器),那么这种行为将会消失。

© www.soinside.com 2019 - 2024. All rights reserved.