我正在使用detachNewThreadSelector
ref和toTarget
自我创建新主题。
线程的目的是轮询移动并根据需要加载图像 - 它循环并且仅在主线程中将原子bool设置为true时退出 - 该线程在对象dealloc
中设置。
问题是由此引起的(来自detachNewThreadSelector引用):
在执行分离线程期间保留对象aTarget和anArgument,然后释放
这意味着我的对象将始终具有(最小)保留计数为1 - 因为该线程不断轮询。因此永远不会调用dealloc
。
所以我的问题是:考虑到轮询线程的存在,如何解除我的对象?
我现在唯一的想法是创建一个对象的destroyThread函数,它设置结束线程bool,它将从我想要要销毁的对象的任何地方调用。这似乎容易出错,有更好的解决方案吗?
提前致谢。
更新
我有另一个解决方案的想法 - 在线程中我检测到保留计数是否为1 - 如果它是1然后我知道线程保持对象存活,所以我打破循环并调用dealloc。这是一个强有力的解决方案吗?
答案 0 :(得分:2)
首先,避免detachNewThreadSelector:
。使用调度队列或NSOperationQueue
几乎可以肯定地做任何你想用它做的事情。即使您需要手动创建一个线程(在现代ObjC中极为罕见),最好创建显式NSThread
对象并保留它们而不是使用detachNewThreadSelector:
来创建一个线程,你可以'与之直接互动。
对于具体问题,如果您创建自己的线程,那么您需要将该bool设置为dealloc
以外的其他位置。这意味着该程序的其他部分需要告诉您关闭。您不能只是通过这种方式释放并自动使用手动线程清理自己。
编辑:永远不要打电话给retainCount
。没有涉及retainCount
的解决方案是一个很好的解决方案。暂且不谈在更一般情况下使用retainCount
的各种实际问题,在这种情况下,它会将您与手动引用计数联系起来。你应该尽快切换到ARC,而retainCount
在ARC中是非法的(它应该在ARC之前是非法的,但他们最终有一个非常好的借口来强迫这个问题)。如果您无法在ARC中实施解决方案,则不太可能是一个好的解决方案。
同样,最佳解决方案是使用GCD调度队列(或通常通过调度队列实现的操作)。除了手动线程管理之外,几乎每个问题都非常高效和有效。
如果必须对遗留代码使用手动线程并且需要维护此类自动销毁,则解决方案是拥有该线程的辅助对象。您的对象拥有辅助对象,该对象具有与线程的保留循环。当您的对象被释放时,它会告诉线程关闭,这会中断保留循环,并且辅助对象会消失。这是管理保留循环的标准方法。
请参阅Apple的Migrating Away From Threads了解更多信息。