假設我有以下功能。
func first() async {
print("first")
}
func second() {
print("second")
}
func main() {
Task {
await first()
}
second()
}
main()
即使將first函式標記為異步沒有任何意義,因為它沒有異步作業,但仍然有可能......
我期待即使第一個函式正在等待,它也會被異步呼叫。
但實際上輸出是
first
second
我將如何異步呼叫 fist 函式來模仿 GCD 的變體:
DispatchQueue.current.async { first() }
second()
uj5u.com熱心網友回復:
該second任務實際上并不等待first在單獨執行緒上運行的任務完成。實際上在first任務中做一些耗時的事情,你會看到second任務實際上根本沒有等待。
使用Task { ... }更多的是DispatchQueue.global().async { first() }. 在first和second任務是在單獨的執行緒上運行,所以你只需要一場比賽,你有沒有保證作為命令print的陳述句運行。(在我的測驗中,它second在first大多數時間之前運行,但它仍然可以偶爾first在second.之前運行。)
那么,問題是,你真的關心這兩個任務的開始順序嗎?如果是這樣,您可以通過(顯然)Task { await first() }在呼叫之后消除競爭second。或者你只是想確保second不會等待first完成?在這種情況下,這已經是行為,不需要更改您的代碼。
你問:
如果
await first()需要在同一個佇列上second()異步運行怎么辦,使用Taskapi是否可行,或者需要 GCD 來實作這一點?
您可以使用現代并發 API 來完成此操作,方法是將例程標記為使用@MainActor. 但請注意,不要將此限定符用于耗時任務本身(因為您不想阻塞主執行緒),而是將耗時操作與 UI 更新解耦,并將后者標記為@MainActor.
例如,這是一個手動異步計算 π 并在完成后更新 UI 的示例:
func startCalculation() {
Task {
let pi = await calculatePi()
updateWithResults(pi)
}
updateThatCalculationIsUnderway() // this really should go before the Task to eliminate any races, but just to illustrate that this second routine really does not wait
}
// deliberately inefficient calculation of pi
func calculatePi() async -> Double {
var value: Double = 0
var denominator: Double = 1
var sign: Double = 1
var increment: Double = 0
repeat {
increment = 4 / denominator
value = sign * 4 / denominator
denominator = 2
sign *= -1
} while increment > 0.000000001
return value
}
func updateThatCalculationIsUnderway() {
statusLabel.text = "Calculating π"
}
@MainActor
func updateWithResults(_ value: Double) {
statusLabel.text = "Done"
resultLabel.text = formatter.string(for: value)
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/348866.html
