6

使用一些代码时,我遇到了运行循环,这是我刚接触的,在NSOperations.

s正忙于下载数据——当他们忙时,有代码以s 和线程休眠NSOperation的形式等待下载完成。NSRunLoop

我特别感兴趣的是这段代码:

while (aCertainConditionIsTrue && [self isCancelled]==NO) {
     if(![[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:1.0]]){
        [NSThread sleepForTimeInterval:1.0];
     }
}

我已阅读有关运行循环的信息,runMode:beforeDate:并将等待输入源或超时。虽然我不是 100% 算作输入源。

在第一次执行时,它总是返回 NO 并点击sleepForTimeInterval:. 这很糟糕吗?

在特定的实用程序类中,它的sleepForTimeInterval:影响很大——每个线程一次——这会严重影响性能。

对此有更好的解决方案或建议吗?

4

2 回答 2

2

睡眠会锁定线程。也许您将代码更改为使用 performSelector:withObject:afterDelay。这样你的线程可以继续运行。

    ...
    done = NO;
    [self checkDoneCondition:nil];
    ...

- (void)checkDoneCondition:(id)object {
    if (aCertainConditionIsTrue && [self isCancelled]==NO) {
        if(...) {
            [self performSelector:@selector(checkDoneCondition:) withObject:[con error] afterDelay:1.0];
        } else {
            done = YES;
        }
    }
}
于 2012-01-20T00:59:39.443 回答
1

看起来您需要使用并发NSOperation。这是 Apple 文档中的相关部分:

与同步运行的非并发操作相比,并发操作异步运行。换句话说,当您调用并发操作的 start 方法时,该方法可能会在相应任务完成之前返回。这可能是因为操作对象创建了一个新线程来执行任务,或者因为操作调用了异步函数。当控制权返回给调用者时操作是否正在进行实际上并不重要,只是它可能正在进行。(...) 在并发操作中,您的 start 方法负责以异步方式启动操作。无论您是生成线程还是调用异步函数,您都可以通过此方法进行操作。开始操作后,您的 start 方法还应该更新 isExecuting 方法报告的操作的执行状态。您可以通过为 isExecuting 键路径发送 KVO 通知来做到这一点,这让感兴趣的客户端知道该操作正在运行。您的 isExecuting 方法还必须以线程安全的方式返回状态。

(来自https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/NSOperation_class/Reference/Reference.html

换句话说,您可以覆盖-startNSOperation 子类中的方法,并为executingandfinished属性设置 ivar。此方法将在单独的线程中开始下载。下载开始时,您设置executing标志并触发 KVO。当它在这个线程中完成时,你对finishedand做同样的事情executing。看起来很复杂,但实际上很简单。

另请参阅 Stack Overflow 上的这个问题,并有一个很好的解释:Subclassing NSOperation to be concurrent and cancellable

于 2012-03-09T21:14:05.200 回答