在我的應用程序中,我在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