如何结束使用detachNewThreadSelector创建的轮询线程



我正在使用detachNewThreadSelector ref和toTarget self创建一个新线程。

线程的目的是在适当的情况下轮询移动和加载图像——它循环,只有当主线程中的原子布尔设置为true时才退出——这是在对象dealloc中设置的。

问题是由以下原因引起的(来自detachNewThreadSelector引用):

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

这意味着我的对象将始终具有一个(最小)保留计数,因为线程会持续轮询。因此CCD_ 4从不被调用。

所以我的问题是:考虑到轮询线程的存在,我如何解除对象的锁定

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

提前谢谢。

更新

我有另一个解决方案的想法——在线程中,我检测保留计数是否为1——如果为1,那么我知道线程正在保持对象的活动,所以我中断循环并调用dealloc。这是一个稳健的解决方案吗?

首先,避免detachNewThreadSelector:。您想用它做的任何事情都可以用调度队列或NSOperationQueue做得更好。即使您需要手动创建线程(这在现代ObjC中非常罕见),也最好创建显式的NSThread对象并保留它们,而不是使用detachNewThreadSelector:来创建无法再直接交互的线程。

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


编辑:永远不要打retainCount。没有涉及retainCount的解决方案是好的解决方案。抛开在更一般的情况下使用retainCount的各种实际问题不谈,在这种情况下,它将手动参考计数联系在一起。你应该尽快切换到ARC,而retainCount在ARC中是非法的(在ARC之前应该是非法的,但他们最终有了一个很好的借口来强制发布)。如果您不能在ARC中实现您的解决方案,那么它不太可能是一个好的解决方案。

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

如果您必须为遗留代码使用手动线程,并且需要维护这种自动析构函数,那么解决方案就是拥有该线程的辅助对象。您的对象拥有辅助对象,该对象与线程有一个保留循环。当您的对象被解除分配时,它会"通知"线程关闭,这会中断retain循环,助手对象就会离开。这是管理保留循环的标准方法。

有关更多信息,请参阅Apple的"从线程迁移"。

最新更新