在我的应用程序中,我在NSOperationQueue内执行了10个异步NSURLConnections作为NSInvocationOperations。为了防止在连接之前返回每个操作有机会完成我打电话CFRunLoopRun()为在这里看到:在iPhone 3GS上消耗100%CPU的后台线程导致潜在主线程
- (void)connectInBackground:(NSURLRequest*)URLRequest {
TTURLConnection* connection = [[TTURLConnection alloc] initWithRequest:URLRequest delegate:self];
// Prevent the thread from exiting while the asynchronous connection completes the work. Delegate methods will
// continue the run loop when the connection is finished.
CFRunLoopRun();
[connection release];
}
一旦连接完成,最终连接代理选择调用CFRunLoopStop(CFRunLoopGetCurrent())恢复在connectInBackground()执行,允许其正常返回:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
TTURLConnection* ttConnection = (TTURLConnection*)connection;
...
// Resume execution where CFRunLoopRun() was called.
CFRunLoopStop(CFRunLoopGetCurrent());
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
TTURLConnection* ttConnection = (TTURLConnection*)connection;
...
// Resume execution where CFRunLoopRun() was called.
CFRunLoopStop(CFRunLoopGetCurrent());
}
这工作得很好,它是线程安全的,因为我捆绑每个连接的响应,并作为TTURLConnection子类的实例变量的数据。
NSOperationQueue声称,将其最大数量的并发操作保留为NSOperationQueueDefaultMaxConcurrentOperationCount允许它动态调整操作的数量,但在这种情况下,它总是会决定1是足够的。由于这不是我想要的,所以我已将最大数目更改为10,现在它严重拖累。
问题是这些线程(在SpringBoard和DTMobileIS的帮助下)消耗了所有可用的CPU时间,并导致主线程变得潜伏。换句话说,一旦CPU被100%利用,主线程就不会像处理UI事件那样快速地处理UI事件,从而保持流畅的UI。具体来说,表格视图滚动变得紧张。
Process Name % CPU
SpringBoard 45.1
MyApp 33.8
DTMobileIS 12.2
...
在用户与屏幕交互或表被滚动主线程的优先级变为1.0(最大可能的)及其运行循环模式成为UIEventTrackingMode。每个操作的线程默认为0.5优先级,异步连接运行在NSDefaultRunLoopMode中。由于我对线程及其运行循环如何根据优先级和模式进行交互的理解有限,我很困惑。
有没有办法在我的应用程序的后台线程中安全地占用所有可用的CPU时间,同时仍然保证为其主线程提供尽可能多的CPU?也许是通过强制主线程按需要频繁运行? (我以为线程优先级将采取的照顾。)
更新12/23: 我终于开始变得对CPU采样器手柄和发现大部分为什么UI变得紧张不安的原因。首先,我的软件正在调用一个具有互斥信号量的库。这些锁在短时间内阻塞主线程,导致滚动略微跳过。
此外,我发现一些昂贵的NSFileManager调用和md5哈希函数,这些函数花费了太多的时间来运行。在主线程中频繁地分配大对象会导致其他一些性能命中。
我已经开始解决这些问题,并且性能已经比以前好很多。我有5个同时连接,滚动顺畅,但我仍有更多工作要做。我打算编写一本关于如何使用CPU采样器来检测和修复影响主线程性能的问题的指南。感谢迄今的评论,他们很有帮助!
UPDATE 1/14/2010: 在达到可接受的性能后,我开始意识到CFNetwork框架偶尔会泄漏内存。CFNetwork内部也随机提供异常(但很少)!我尽我所能来避免这些问题,但没有奏效。我很确定这些问题是由NSURLConnection本身的缺陷造成的。我写了测试程序,除了练习NSURLConnection之外什么也没做,他们仍然崩溃和泄漏。
最终我用ASIHTTPRequest替换了NSURLConnection,崩溃完全停止。 CFNetwork 差不多永远不会泄漏,但是,解析DNS名称时仍会出现一个非常罕见的泄漏。我现在很满意。希望这些信息能为你节省一些时间!
我建议不要让线程在手机上占用100%的CPU。你会很快耗尽电池。 – 2009-12-21 17:42:56
如果用户想要更多内容,他们将滚动以获取内容。 CPU仅在用户请求时才使用。可可的线程模型不应该有这样的问题。跟踪UI事件和后台线程仅为0.5时,主线程以1.0优先级运行。我想为主线程分配有保证的CPU时间。那可能吗? – 2009-12-21 19:10:59