0

我正在尝试解决围绕 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 循环。

显然,似乎在这个处理之外有一些东西经常减慢这种性能。

很想知道您是否遇到过类似的问题,或者您是否有任何可以帮助我的提示/花絮。

提前致谢..

4

1 回答 1

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 类甚至不应该在后台线程上发布,因为发布可能会导致 a -dealloc,这在 UIKit 类中可能不是线程安全的。(哎哟。)

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

你也处于可能的极限:我很确定 iOS 时间片是 10 毫秒,这意味着如果有任何其他事情需要 CPU (并且有很多后台进程;尝试在仪器有时)您的动画可能会出现滞后。

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

你可能对 CADisplayLink 有更好的运气,它与显示器的刷新率同步(我认为你通过了它[UIScreen mainScreen])并且设计用于动画,所以它应该表现得更好一些。iOS 3.1+,但我怀疑支持 3.0 没什么意义。

于 2011-06-30T02:42:48.020 回答