我正在使用苹果的 AVAudioEngine 代码,如下所示:
var audioEngine = AVAudioEngine()
audioEngine.inputNode.installTap { [buffer, when] in
let waveform = myGetWaveform(buffer)
Task {
await Something.shared.doSomethingWith(waveform)
}
}
installTap 的闭包将在某个音频线程上执行。
我这样做是因为
Something
是一个actor
,而且我很难改变它。但当然,问题是那些 Task
可能会乱序执行。那会很糟糕 - 我需要它们按顺序执行。如何保证它们按顺序执行?我想这可以应用于任何无法将调用者更改为异步的同步代码。我似乎找不到任何方法将序列化注入异步参与者代码中。
我发现的许多版本(使用信号量等)似乎都打破了异步的“线程必须向前移动”契约...
澄清:
await
,抱歉。
buffer
将包含从设备麦克风采样的音频波形数据。这就是难题:在我给出的实现中,每个新的音频缓冲区都会一遍又一遍地调用
doSomethingWith
,但不一定会按顺序调用。
ClosureIsolation 功能实现,该功能应该很快就会出现在 Swift 6 中。
如果您等不及使用此功能的 Swift 版本,那么您最好的工具是AsyncStream。您将yield
消息发送到流,Actor 将循环使用它们。您的 Actor 需要提供一个包含流的
nonisolated
属性,以便您的同步代码可以访问它。