0

我正在使用detachNewThreadSelector reftoTargetself 创建一个新线程。

该线程的目的是轮询运动并在适当的时候加载图像-它循环并且仅当主线程中的原子布尔设置为true时才退出-这是在对象中设置的dealloc

问题是由此引起的(来自 detachNewThreadSelector 参考):

aTarget 和 anArgument 对象在分离线程执行期间被保留,然后被释放

这意味着我的对象将始终具有(最小)保留计数 1 - 因为线程不断轮询。dealloc因此永远不会被调用。

所以我的问题是:考虑到轮询线程的存在,我如何释放我的对象?

我现在唯一的想法是创建一个对象的destroyThread函数,它设置结束线程bool,它将从我希望对象被销毁的任何地方调用。这似乎容易出错,有更好的解决方案吗?

提前致谢。

更新

我有另一个解决方案的想法 - 在线程中我检测保留计数是否为一 - 如果它是一,那么我知道线程正在保持对象处于活动状态,所以我打破循环并调用 dealloc。这是一个强大的解决方案吗?

4

1 回答 1

2

首先,避免detachNewThreadSelector:。几乎可以肯定,使用调度队列或NSOperationQueue. 即使您需要手动创建一个线程(这在现代 ObjC 中极为罕见),最好创建显式NSThread对象并保留它们,而不是使用detachNewThreadSelector:它创建一个您无法再直接与之交互的线程。

对于特定问题,如果您创建自己的线程,那么您需要将该 bool 设置为dealloc. 这意味着程序的其他部分需要告诉您关闭。您不能以这种方式被释放并使用手动线程自动清理自己。


编辑:永远不要打电话给retainCount. 没有涉及的解决方案retainCount是一个好的解决方案。撇开retainCount在更一般的情况下使用的各种实际问题不谈,在这种情况下,它与您手动引用计数有关。您应该尽快切换到 ARC,并且retainCount在 ARC 中是非法的(在 ARC 之前它应该是非法的,但他们终于有了一个很好的借口来强迫这个问题)。如果您无法在 ARC 中实施您的解决方案,那么它不太可能是一个好的解决方案。

同样,最好的解决方案是使用 GCD 调度队列(或操作,通常使用调度队列实现)。对于几乎所有问题,它都比手动线程管理更加高效和有效。

如果您必须为遗留代码使用手动线程并且需要维护这种自动销毁,则解决方案是拥有该线程的辅助对象。您的对象拥有辅助对象,该对象与线程有一个保留循环。当您的对象被释放时,它会告诉线程关闭,从而中断保留循环,并且帮助对象消失。这是管理保留循环的标准方法。

有关更多信息,请参阅 Apple 的Migrating Away From Threads

于 2012-07-19T19:12:29.480 回答