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

时间:2012-07-19 18:50:50

标签: objective-c ios multithreading nsthread

我正在使用detachNewThreadSelector reftoTarget自我创建新主题。

线程的目的是轮询移动并根据需要加载图像 - 它循环并且仅在主线程中将原子bool设置为true时退出 - 该线程在对象dealloc中设置。

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

  

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

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

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

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

提前致谢。

更新

我有另一个解决方案的想法 - 在线程中我检测到保留计数是否为1 - 如果它是1然后我知道线程保持对象存活,所以我打破循环并调用dealloc。这是一个强有力的解决方案吗?

1 个答案:

答案 0 :(得分:2)

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

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


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

同样,最佳解决方案是使用GCD调度队列(或通常通过调度队列实现的操作)。除了手动线程管理之外,几乎每个问题都非常高效和有效。

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

请参阅Apple的Migrating Away From Threads了解更多信息。