如何解决使用操作来管理函数调用之间的不平衡
我正在编写一个 VideoPlayer()
类,该类具有 start()
和 stop()
函数来启动给定视频的播放。 VideoPlayer()
的每个实例管理一个视频
start()
和 stop()
函数是异步的,我通过成功/失败的委托得到通知。此委托由第三方 SDK 完成。
class VideoPlayer {
func start() {
// Async call
}
func stop() {
// Async call
}
// Callback from third party library with status
func videoDidStart(view: UIView) {
// Notify clients
}
func videoDidStop(stopped: Bool) {
// Notify clients
}
}
我有客户调用 start()
和 stop()
函数,但有时碰巧他们会快速连续调用 start/stop。这会导致意外行为。
例如,如果客户端在上一次调用 start()
之前调用 stop()
,视频将不会播放。
理想情况下,客户端会等到我发送通过代表收到的成功/失败通知。
当然,这不会发生,我的任务是让 VideoPlayer()
类管理 start()
和 stop()
之间的不平衡,并将所有调用排队,以便一切按顺序执行。
我希望 VideoPlayer()
类确保每次 start()
和 stop()
之间出现不平衡时,每个 start()
都与一个 stop()
匹配并且将流氓调用放入队列中,并在解决不平衡问题后执行它们。
我如何管理这样的事情?我相信我需要使用 Operations
与 start()
和 stop()
之间的依赖关系。我是否应该将 start()/stop()
设为单个操作并将恶意调用排入队列,直到操作完成。
我可以使用其他方法吗?我查看了 dispatch_groups
和 dispatch_barriers
,但不确定它们是否适合我的用例。
任何帮助将不胜感激。谢谢
解决方法
我不明白为什么需要手术。作为您所描述的那种事情的粗略示例,我制作了一个小型调度程序架构:
struct Start {
let callback : () -> ()
var started = false
}
class Dispatcher {
var q = [Start]()
func start(_ f: @escaping () -> ()) {
q.append(Start(callback:f))
self.startFirstOne()
}
func stop(_ f: @escaping () -> ()) {
// assume this can only refer to the first one in the queue
DispatchQueue.main.asyncAfter(deadline: .now()+DispatchTimeInterval.seconds(Int.random(in: 1...10))) {
self.q.removeFirst()
f()
self.startFirstOne()
}
}
private func startFirstOne() {
guard !q.isEmpty else { return }
guard !q[0].started else { return }
print("starting")
self.q[0].started = true
DispatchQueue.main.asyncAfter(deadline: .now()+DispatchTimeInterval.seconds(Int.random(in: 1...10))) {
self.q.first!.callback()
}
}
}
start
调用已排队,在收到足够多的 stop
调用以将其置于队列前面之前,我们实际上不会启动调用。
我个人根本不喜欢这个,因为我们对合同遵守做出了三个非常强烈的假设:
-
我们假设每个调用
start
的人也会调用stop
, -
并且我们假设调用
start
的人在从stop
调用中被回调之前不会调用start
, -
而且我们假设没有调用
start
的人永远不会调用stop
。
然而,如果每个人都确实遵守合同,那么每个人的 stop
都会被回调对应于该人的 start
。这是一个粗略的测试平台,使用随机延迟来模拟异步性:
let d = Dispatcher()
DispatchQueue.main.asyncAfter(deadline: .now()+DispatchTimeInterval.seconds(Int.random(in: 1...10))) {
d.start {
print("hearts start")
DispatchQueue.main.asyncAfter(deadline: .now()+DispatchTimeInterval.seconds(Int.random(in: 1...10))) {
d.stop { print("hearts stop") }
}
}
}
DispatchQueue.main.asyncAfter(deadline: .now()+DispatchTimeInterval.seconds(Int.random(in: 1...10))) {
d.start {
print("diamonds start")
DispatchQueue.main.asyncAfter(deadline: .now()+DispatchTimeInterval.seconds(Int.random(in: 1...10))) {
d.stop { print("diamonds stop") }
}
}
}
DispatchQueue.main.asyncAfter(deadline: .now()+DispatchTimeInterval.seconds(Int.random(in: 1...10))) {
d.start {
print("clubs start")
DispatchQueue.main.asyncAfter(deadline: .now()+DispatchTimeInterval.seconds(Int.random(in: 1...10))) {
d.stop { print("clubs stop") }
}
}
}
DispatchQueue.main.asyncAfter(deadline: .now()+DispatchTimeInterval.seconds(Int.random(in: 1...10))) {
d.start {
print("spades start")
DispatchQueue.main.asyncAfter(deadline: .now()+DispatchTimeInterval.seconds(Int.random(in: 1...10))) {
d.stop { print("spades stop") }
}
}
}
试试看,你会发现,无论这些东西运行的顺序和时间如何,开始-停止对都由调度员维护。
正如我所说,我不喜欢它。我更愿意假设来电者可能不遵守合同并准备对此采取行动。但这就是它的价值。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。