当应用程序在后台进行一些计算时,我想设置一些加载点的动画。我通过NSTimer
:实现这一点
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.3f
target:self
selector:@selector(updateLoadingPoints:)
userInfo:nil
repeats:YES];
不幸的是,有时,当计算量变得相当大时,该方法不会被激发,因此更新不会发生。似乎所有的激发都在一个队列中,该队列是在繁重的计算之后激发的。
有没有办法给NSTimer
更高的优先级,以确保它定期调用我的方法?或者还有其他方法可以实现这一点吗?
NSTimer的工作原理是将事件添加到主运行循环的队列中;它与用于触摸事件和I/O数据接收事件等的事件队列相同。您设置的时间间隔不是精确的时间表;基本上,在每次通过运行循环时,都会检查计时器,看是否有任何计时器将被触发。
由于它们的实现方式,无法增加计时器的优先级。
听起来,您的辅助线程占用了主线程大量的CPU时间,因此计时器不会像您希望的那样频繁启动。换句话说,主线程因CPU时间而不足。
调用performSelectorOnMainThread:
不一定有帮助,因为这些方法本质上是向主线程的事件队列添加一个触发计时器。所以你只需要以不同的方式设置计时器。
为了解决您的问题,我建议您通过降低计算线程的优先级来增加主线程的相对优先级。(参见[NSThread setThreadPriority:]
。)
让你的重要辅助线程以比主线程更低的优先级运行似乎有违直觉,这只是在屏幕上绘制东西,但在一个人性化的应用程序中,保持屏幕最新并响应用户输入通常是应用程序应该做的最重要的事。
在实践中,主线程只需要很少的CPU,所以它不会真正降低工作线程的速度;相反,您只是确保在主线程需要做一些事情的少量时间内,它能很快完成。
计时器被添加到计划的运行循环中。如果您在辅助线程(例如您的工作线程)上创建计时器,则很有可能您也在辅助线程上调度了计时器。
您希望在主线程上更新UI。因此,您希望在主线程上调度计时器。如果你的更新仍然很慢,也许你的主线程可以做更少的工作,并确保你的线程数量非常少,并且你正在适当地锁定。
我怀疑你是在一个次要线程上创建的,这个线程并没有像计时器想要触发的那样频繁地运行运行循环。如果它在后台做了大量(长时间)的工作,而没有运行运行循环,那么计时器将没有机会触发,因为当线程仍在处理时,消息将没有机会被触发。
从单独的线程而不是主线程进行计时器调用。这肯定会使它与其他主线程的处理分离,这将给您带来所需的结果。
使用performSelectInBackground:withObject在单独的线程上执行计算。在你的UI循环中总是尽可能少地做,因为这里所做的任何工作都会阻止鼠标点击,导致SPoD/beachball,并延迟计时器处理程序。
我怀疑不仅仅是您的TIMER没有响应,而是整个UI都没有响应。
很抱歉在我之前的修订版中调用了错误的API-复制/粘贴失败。