AKMetronome倒计时,如何从后台线程发布到主线程启动录音机?
AKMetronome countdown, how to publish to main thread from background thread to start recorder?
我一直在研究如何使用 AudioKit 库实现节拍器倒计时,但 运行 遇到与线程和我的实现相关的问题。
我的实现使用 AudioKit AKMetronome
,一种处理 metronome.start
的方法,metronome.callback
处理程序在给定数量的小节完成后启动 recording
。
init () {
metronome.callback = handler
}
func record () {
self.metronome.start()
}
处理程序及时计算节拍器位置,如果所需的小节数完成(倒计时),记录器将启动。
不幸的是,运行 AKNodeRecorder
的 .record
在 AKMetronome
的 .callback handler
导致警告信息:
Publishing changes from background threads is not allowed; make sure to publish values from the main thread (via operators like receive(on:)) on model updates.
因此,在 metronome.callback
处理程序中开始录制的调用通过 GCD API:
传递到主线程
DispatchQueue.main.sync {
do {
try self.recorder.record()
} catch {
print("[ERROR] Oops! Failed to record...")
}
}
我已经使用 .sync
阻塞方法来尽可能立即解决计算,因为
时序在音频应用程序中至关重要(理想情况下,调用应在实时线程中执行);我的理解是 GCP API main thread
提供最高优先级,但我不确定这是否是对时间敏感的应用程序的最佳选择?
如果可能,想从其他用户那里得到一些反馈或指导,谢谢!
好的,所以实际问题与节拍器或倒计时无关?您真正想知道的是:从后台线程使用 sync
会让我更快地进入主线程吗?
如果是:基本没有。这不是 sync
的用途或含义。 async
/sync
差异对速度完全没有影响。如果你使用 async
进入主线程,你会在它空闲时立即进入,所以你说 sync
什么也得不到。
此外,如果您已经在 async
后台线程中进入回调,那么任何可以造成的损害都已经造成;你的时间现在不准确,除非你口袋里正好有一台时间机器,否则你绝对无能为力。
根据@matt 关于回调内部调用的建议,我根据 Timer
的 .scheduledTimer
更改了方法。
func record () {
metronome.restart()
Timer.scheduledTimer(withTimeInterval: self.barLength, repeats: false) { _ in
self.startRecording()
print("Timer fired!")
}
}
record
是 handler
启动 AKMetronome
,选择使用 .restart
以便每次请求都从头开始。
A 属性 .barLength
保存 the desired countdown
的计算长度值。调用的 .startRecording
方法是处理 AKRecorder .record
调用的处理程序。
未来 reader,请记住 Timer
并不意味着根据 (Accuracy of NSTimer) 是准确的,但是
不幸的是,这是迄今为止我测试过的最好的方法。
我一直在研究如何使用 AudioKit 库实现节拍器倒计时,但 运行 遇到与线程和我的实现相关的问题。
我的实现使用 AudioKit AKMetronome
,一种处理 metronome.start
的方法,metronome.callback
处理程序在给定数量的小节完成后启动 recording
。
init () {
metronome.callback = handler
}
func record () {
self.metronome.start()
}
处理程序及时计算节拍器位置,如果所需的小节数完成(倒计时),记录器将启动。
不幸的是,运行 AKNodeRecorder
的 .record
在 AKMetronome
的 .callback handler
导致警告信息:
Publishing changes from background threads is not allowed; make sure to publish values from the main thread (via operators like receive(on:)) on model updates.
因此,在 metronome.callback
处理程序中开始录制的调用通过 GCD API:
DispatchQueue.main.sync {
do {
try self.recorder.record()
} catch {
print("[ERROR] Oops! Failed to record...")
}
}
我已经使用 .sync
阻塞方法来尽可能立即解决计算,因为
时序在音频应用程序中至关重要(理想情况下,调用应在实时线程中执行);我的理解是 GCP API main thread
提供最高优先级,但我不确定这是否是对时间敏感的应用程序的最佳选择?
如果可能,想从其他用户那里得到一些反馈或指导,谢谢!
好的,所以实际问题与节拍器或倒计时无关?您真正想知道的是:从后台线程使用 sync
会让我更快地进入主线程吗?
如果是:基本没有。这不是 sync
的用途或含义。 async
/sync
差异对速度完全没有影响。如果你使用 async
进入主线程,你会在它空闲时立即进入,所以你说 sync
什么也得不到。
此外,如果您已经在 async
后台线程中进入回调,那么任何可以造成的损害都已经造成;你的时间现在不准确,除非你口袋里正好有一台时间机器,否则你绝对无能为力。
根据@matt 关于回调内部调用的建议,我根据 Timer
的 .scheduledTimer
更改了方法。
func record () {
metronome.restart()
Timer.scheduledTimer(withTimeInterval: self.barLength, repeats: false) { _ in
self.startRecording()
print("Timer fired!")
}
}
record
是 handler
启动 AKMetronome
,选择使用 .restart
以便每次请求都从头开始。
A 属性 .barLength
保存 the desired countdown
的计算长度值。调用的 .startRecording
方法是处理 AKRecorder .record
调用的处理程序。
未来 reader,请记住 Timer
并不意味着根据 (Accuracy of NSTimer) 是准确的,但是
不幸的是,这是迄今为止我测试过的最好的方法。