macOS 中控制台应用程序内的异步/等待用法

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

我对 Swift 中的

async
/
await
概念还很陌生。所以我给自己开发了一个小游乐场:

import Foundation

func dummyLoop() async {
    print("inside dummy fcn")
    for i in 0 ..< 10 {
        if Task.isCancelled {
            return
        }
        print("Loop \(i)")
        try? await Task.sleep(for: .seconds(1))
    }
}

let task = Task(priority: .high) {
    await dummyLoop()
}

print("Press any key to stop task...")
_ = readLine()
task.cancel()
print("Press any key to stop finish app...")
_ = readLine()
print("Ciao")

所以我想运行一些虚拟循环并在控制台中按 Enter 后停止它。但我看到任务关闭根本没有执行。我发现这种行为在某种程度上与

RunLoop
有关...有人可以解释一下这里发生了什么吗?我应该如何运行
Task
在控制台应用程序中并行执行?

swift async-await task command-line-tool
1个回答
1
投票

Task.init
继承参与者上下文,在本例中是主要参与者。主要参与者在主线程上运行,但主线程被
readLine
阻塞,因此什么也做不了。

您可以使用

Task.detached
来代替,它在协作线程池中的某个线程上运行任务。

let task = Task.detached(priority: .high) {
    await dummyLoop()
}

或者,您可以从 stdin 异步读取,而不是使用会阻塞的

readLine

var iterator = FileHandle.standardInput.bytes.lines.makeAsyncIterator()
print("Press any key to stop task...")
_ = try await iterator.next()
task.cancel()
print("Press any key to stop finish app...")
_ = try await iterator.next()
print("Ciao")

在打印消息中,您提到“按任意键...”,但是

readLine
和异步读取行都无法实现这一点。无论哪种情况,程序都会等待返回键。要检测任何按键,您可以使用
这篇文章
中的enableRawMode

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