当应用程序进行大量计算时,NSTimer有时会冻结

时间:2012-01-09 10:30:31

标签: objective-c multithreading cocoa-touch ios5 heavy-computation

我想在应用程序在后台进行一些计算时为一些加载点设置动画。我通过NSTimer

实现了这一目标
    self.timer = [NSTimer scheduledTimerWithTimeInterval:0.3f
                                             target:self 
                                           selector:@selector(updateLoadingPoints:) 
                                           userInfo:nil 
                                            repeats:YES];

不幸的是,有时,当计算变得非常繁重时,不会触发该方法,因此不会发生更新。似乎所有的射击都在队列中,这是在繁重的计算之后被解雇的。

有没有办法让NSTimer具有更高的优先级,以确保它定期调用我的方法?或者还有另一种方法来实现这一目标吗?

4 个答案:

答案 0 :(得分:3)

NSTimer的工作原理是在主运行循环中向队列添加事件;它是用于触摸事件和I / O数据接收事件的相同事件队列等。您设置的时间间隔不是精确的时间表;基本上每次通过运行循环时,都会检查计时器是否有任何原因被触发。

由于它们的实现方式,无法提高计时器的优先级。

听起来你的辅助线程占用主线程的大量CPU时间,因此定时器不会像你想的那样频繁发射。换句话说,主线程缺乏的CPU时间。

调用performSelectorOnMainThread:不一定有帮助,因为这些方法实质上是向主线程的事件队列添加单火定时器。所以你只是以不同的方式设置计时器。

要解决您的问题,我建议您通过降低计算线程的优先级来增加主线程的相对优先级。 (见[NSThread setThreadPriority:]。)

让重要的工作线程以比主线程更低的优先级运行似乎是违反直觉的,主线程只是将内容绘制到屏幕上,但是在人性化的应用程序中,保持屏幕更新并响应用户输入通常是应用程序应该做的最重要的事情。

实际上,主线程需要很少的CPU,所以它不会真正减慢你的工作线程;相反,你只是确保主线程需要做的少量时间,它会很快完成。

答案 1 :(得分:0)

计时器被添加到已安排的运行循环中。如果您在辅助线程(例如您的工作线程)上创建计时器,那么您很有可能还在辅助线程上安排它。

您希望主线程上的UI更新。因此,您希望在主线程上安排计时器。如果您的更新仍然很慢,也许您的主线程可以减少工作量,并确保您拥有非常少的线程,并且您正确地锁定。

我怀疑你是在次要线程上创建的,它没有像计时器想要触发的那样经常运行运行循环。如果它在后台执行了很多(长时间)工作,并且没有运行run循环,那么计时器将没有机会触发,因为当它的线程仍在处理时,消息将无法被触发

答案 2 :(得分:-1)

从单独的线程而不是主线程进行定时器调用。这肯定会与你的其他主线程处理分开,这将为你提供所需的结果。

答案 3 :(得分:-1)

使用performSelectorInBackground:withObject在单独的线程上执行计算。始终在UI循环中尽可能少地做,因为这里完成的任何工作都会阻止鼠标点击,导致SPoD /沙滩球和延迟计时器处理程序。

我怀疑这不仅仅是你的TIMER没有反应,而是整个用户界面。

很抱歉在我之前的版本中调出了错误的API - 我自己复制/粘贴失败。