deinit {
print("deinit")
}
DispatchQueue.global().async { [weak self] in
while(true){
print(self)
print("sleep")
sleep(1)
}
}
尽管在课堂上被称为deinit
,
DispatchQueue.global()
中的无限循环仍然有效。
在这种情况下,例如,
可选(
) 睡觉
可选(
) 睡觉
取消初始化(在取消初始化之后)
无
睡觉
无
睡觉
...(重复)
答案 0 :(得分:2)
全局调度队列不在应用程序的类中。它在系统中。您已经启动了一个独立线程,并且该线程一直运行直到其操作结束为止,在这种情况下,它永远不会运行。这与您的类是否获得deinit
和实例不再存在无关。
实际上,一个常见的错误是启动一个独立线程,一段时间后,引用了您的实例。如果同时调用了您的实例deinit
,则可能发生各种可怕的事情,从崩溃到deinit
之后实例一直处于不确定状态都可以发生。
但是,这不是在这里发生;您已经正确使用了weak self
,因此您的实例确实已经按照nil
的说明以良好的顺序消失了。因此,您所看到的是预期的行为,尽管显然这在现实生活中并不是一件好事。
答案 1 :(得分:1)
GCD独立于对象的生命周期管理队列(以及分配给这些队列的任务)。
FWIW,您正在使用全局队列这一事实与手头的问题无关。使用自定义调度队列(或操作队列)会产生完全相同的行为:
let queue = DispatchQueue(label: "private_queue")
queue.async { [weak self] in
while true {
print(self)
print("sleep")
sleep(1)
}
}
除非您明确退出循环(使用while
测试,或者如果要手动取消,使用{{ 3}})。
GCD不执行抢先取消。
注意,此调度任务当前正在运行甚至不相关。所分配的任务是否已完成才很重要。 self == nil
循环无关紧要。考虑:
while
这会将100个任务排入该自定义串行队列。但是,如果let queue = DispatchQueue(label: "private_queue")
for i in 0 ..< 100 {
queue.async { [weak self] in
print("iteration \(i) queued by \(self)")
Thread.sleep(forTimeInterval: 1)
}
}
print("done dispatching")
在所有这些任务完成之前被释放,则此队列将继续处理这100个已分派的任务。
最重要的是,尽管我们可以谈论GCD对全局队列的管理,但这并不是一个突出的问题。关键观察结果是:
添加到调度队列中的任务(或添加到操作队列中的操作)有效地保持对其各自队列的强引用;
已分派的工作项(或操作)将继续执行,而不管排队它的对象可能已被释放的事实(当然,除非您测试self
);和
即使已分派的任务(或操作)尚未开始,它也将保留在该队列中,直到完成执行(或您手动取消它)为止...再一次,与进入队列的对象是否无关紧要它是否已被释放。
答案 2 :(得分:0)
DispatchQueue.global()返回全局系统队列。 https://developer.apple.com/documentation/dispatch/dispatchqueue/2300077-global
GCD管理一个共享线程池,确定并向全局调度队列添加代码块以执行该代码。
您在调度队列上执行的执行与DialogFlowPopUpController实例的 deinit
不相关// your execution should not be completed because there are no break statement
{ [weak self] in
while(true){
print(self)
print("sleep")
sleep(1)
}
}
如何更改执行以打破无限循环
DispatchQueue.global().async { [weak self] in
while(self != nil){
print(self)
print("sleep")
sleep(1)
}
}