NSTimer / NSOperationQueue执行不一致的iphone

时间:2011-06-30 01:41:56

标签: iphone nstimer nsoperationqueue

我正在尝试解决围绕NSTimer / NSOperationQueue执行不一致的UI问题。我看到无论我是否使用NSTimer或NSInvocationOperation来触发下面的代码,很多时候性能都是需要的,但是几次行为很慢(并且如下例所示,代码运行时间超过1秒) )。

这是我通过NSInvocationOperation调用的代码:

-(void) progressAsynch{
    for (count = 1; count<=100; count++) {

        // Reposition Label's CGRect.
        [self performSelectorOnMainThread:@selector(moveLabelToNewPosition) withObject:nil waitUntilDone:YES];

        //Update the progress of the progress view
        [self performSelectorOnMainThread:@selector(advanceProgressViewProgress) withObject:nil waitUntilDone:YES];

        //Sleep for 10 millisecs
        [NSThread sleepForTimeInterval:0.01];

        //if the progress view has progressed fully call main thread to to next tasks.
        if(progressView.progress == 1) {
            [self performSelectorOnMainThread:@selector(processResult) withObject:nil waitUntilDone:YES];
        }
    }

}

NSTimer调用的方法代码(每10毫秒触发一次)与上面非常相似,只是它不会有for循环。

显然,这种处理之外的某些内容似乎经常会降低这种性能。

很想知道你是否遇到类似的问题,或者你是否有任何可能帮助我的指针/花絮。

提前致谢..

1 个答案:

答案 0 :(得分:0)

线程间通信速度不快,waitUntilDone:YES增加了额外的线程同步开销,完全没必要(我非常确定performSelectors是序列化的)。你可能会有更好的运气,比如

-(void) progressAsynch{
    for (count = 1; count<=100; count++) {
        [self performSelectorOnMainThread:@selector(stuff) withObject:nil waitUntilDone:NO];
        [NSThread sleepForTimeInterval:0.01];
    }
}

然而,这仍然不好。看起来self是一个视图或视图控制器,它将由NSInvocation保留,并且可能在后台线程上发布。 UIKit的大多数都不是线程安全的; Game Center示例代码转到伟大的长度,表明UIKit类甚至不应该在后台线程上发布,因为发布可能会导致-dealloc,这在UIKit类中可能不是线程-安全。 (哎哟。)

(另请注意,您对progressView.progress的调用对后台线程并不安全。)

你也处于可能的极限:我很确定iOS时间片是10毫秒,这意味着如果其他任何东西需要CPU(并且有很多后台进程;请尝试使用在某些时候仪器中的活动监视器)您的动画可能看起来滞后。

最后,通过一些音频播放代码,我们注意到NSTimer不是很准确。我不知道为什么。我认为我们用一些使用SIGALRM的东西(以及可能不信号安全,感叹的代码)来修复它。

您可能会更好地使用CADisplayLink,它与显示器的刷新率同步(我认为您将其传递给[UIScreen mainScreen])并且设计为动画使用,因此它应该会更好一些。 iOS 3.1+,但我怀疑支持3.0没什么意义。