有没有一种方法可以无限期暂停NSThread并使其从另一个线程恢复?

5

看起来这些是使NSThread休眠的唯一方法

* sleepForTimeInterval:

* sleepUntilDate:

这样问是否不好的做法?

实际上,现在并不清楚你正在问什么... - Quinn Taylor
3个回答

17

如果您希望您的线程一直停止,直到其他线程告诉它再次启动,那么您可以使用NSConditionLock。 NSConditionLock类似于条件变量,具有一些基本方法:lockWhenCondition、unlockWithCondition和lock。典型用法是在后台线程上使用“lockWhenCondition:”等待条件锁,而在前台线程中设置条件,这会导致后台线程醒来。条件是一个简单的整数,通常是枚举。

以下是示例:

enum {
    kWorkTodo = 1,
    kNoWorkTodo = 0
}

- (id)init {
    if ((self = [super init])) {
        theConditionLock = [[NSCoditionLock alloc] initWithCondition: kNoWorkTodo];
        workItems = [[NSMutableArray alloc] init];
    }
}

- (void)startDoingWork {
    [NSThread detachNewThreadSelector:@selector(doBackgroundWork) toTarget:self withObject:nil];
}

- (void)doBackgroundWork:(id)arg {
    while (YES) {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        NSArray *items = nil;
        [theConditionLock lockWhenCondition:kWorkTodo]; // Wait until there is work to do
        items = [NSArray arrayWithArray:workItems]
        [workItems removeAllObjects];
        [theConditionLock unlockWithCondition:kNoWorkTodo];
        for(id item in items) {
            // Do some work on item.
        }
        [pool drain];
    }
}

- (void)notifyBackgroundThreadAboutNewWork {
    [theConditionLock lock];
    [workItems addObject:/* some unit of work */];
    [theConditionLock unlockWithCondition:kWorkTodo];
}
在这个例子中,当调用startDoingWork时,doBackgroundWork:会在后台线程上启动,但由于没有工作要做,它会立即停止。一旦调用notifyBackgroundThreadAboutNewWork,然后doBackgroundWork:将启动并处理新的工作,然后回到休眠状态等待新的工作可用,这将在下次调用notifyBackgroundThreadAboutNewWork时发生。

1
非常感谢您的解决方案。这似乎是我需要的。 - yan bellavance
因此,使用NSlock协调线程的过程,在线程之间是否具有非常低的延迟。我尝试使用NSthread的sleep方法,但速度非常慢。 - yan bellavance
你能告诉我为什么在 [theConditionLock unlockWithCondition:kNoWorkTodo] 之前和之后都要做一些工作吗?另外,NSLock 和 NSConditionLock 有什么区别? - yan bellavance
3
当锁定时,他所做的不完全是工作。 workItems数组是一个收件箱;notifyBackgroundThreadAboutNewWork方法将新项留在其中,而在lockWithCondition:unlockWithCondition:消息之间的代码将这些项提取到一个新数组(items)中。所有真正的工作都发生在unlockWithCondition:之后,并且使用该临时items数组。 - Peter Hosey
2
他正在使用条件锁作为同步点,以允许一个线程向另一个线程发出信号,表明它可以继续进行其正在进行的操作。lockWhenCondition调用有效地导致后台线程“无限期”休眠(正如您所说),直到前台线程指定满足了条件。至于NSLock和NSConditionLock之间的区别,如果您阅读文档,那么这显然是非常明显的。使用NSLock,每个人都在同一件事上锁定。条件锁可以指定N个不同的条件,这允许更精细的锁定。 - Quinn Taylor
显示剩余3条评论

2
如果您确实有需要在后台线程执行的任务,但其中一个任务需要在另一个任务完成之后才能执行,我建议您查看NSOperation和NSOperationQueue。NSOperation支持设置非常复杂的依赖关系,而NSOperationQueue将根据适当的顺序处理并执行这些操作,使用合适数量的后台线程。苹果公司的文档对此有很好的介绍,并且Drew McCormack在MacResearch上也有一篇不错的文章。请参考:文档文章

0

你想做什么并不清楚。停止线程并在新线程上恢复相同的函数?(这是毫无意义的——旧线程有什么问题吗?)停止线程并在另一个现有线程上恢复相同的函数?

无论哪种方式,都不可能,也不是一个好主意。正确的解决方案是将您的函数分成两个部分,然后使用一些或所有运行循环、NSTimer、performSelector…方法和NSPort来实现您想要做的任何事情。

如果您设想的黑暗线程魔法没有发生,您的程序将工作得更好。


1
你不明白我想随时停止线程。因此,拆分任务是毫无意义的。 - yan bellavance
2
你为什么想要这样做呢?如果你想停止正在进行的工作,那就停止吧。否则,你很可能会在某个地方停止线程,导致该任务只完成了一半。 - Peter Hosey
1
你意识到吗,你不是在帮助我,而是在争论。我不知道你是怎么达到10k的。 - yan bellavance
2
我通过帮助人们接近了10k。这也是我在这里尝试做的事情。看起来我没有成功;Jon Hess比我更清楚你想要什么。 - Peter Hosey
1
你确实问了这是否是不好的做法,他正在回答你。他获得声望点数的方式与其他人相同:提供人们认为有用的答案。如果你想要一个清晰的答案,我建议你从一开始就提出一个清晰的问题。(例如,解释为什么或者你希望实现什么可能会导致比最初显而易见的更好的想法)。我很高兴你找到了一个有助于回答你问题的答案,但请知道,我们大多数人可能和彼得一样困惑。 - Quinn Taylor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接