2012-11-05 31 views
0

我有一個應用程序,其網絡活動在其單獨的線程中完成(並且網絡線程不斷從服務器獲取數據並更新顯示 - 顯示調用已完成回到主線程)。當用戶註銷時,主線程調用上的網線斷開方法如下:performSelector:OnThread:waitUntilDone不會一直執行選擇器

[self performSelector:@selector(disconnectWithErrorOnNetworkThread:) onThread:nThread withObject:e waitUntilDone:YES]; 

這個選擇被調用的大部分時間,一切工作正常。然而,這個調用永遠不會返回(換句話說,選擇器永遠不會執行)並且線程和應用程序掛起的時候(可能是十次中的兩次)。任何人都知道爲什麼performSelector行爲不正常?

請注意,我需要等到呼叫得到執行,這就是爲什麼waitUntilDone爲YES,因此將其更改爲NO不適用於我。此外,網絡線程的運行循環正在運行(我在創建線程時明確地啓動它)。

請注意,由於數據傳輸的連續性,我需要明確使用NSThreads而不是GCD或Operations隊列。

+1

當斷開連接失敗時,您是否暫停了調試程序以查看哪些代碼正在運行?它可能正處於數據傳輸的中間,因此直到下一次運行循環時纔會取消該數據塊的發送或接收。 – Joe

+0

Joe,小數據交換中收到數據,因此一旦當前數據傳輸結束,就應該調用選擇器。運行循環應在完成當前數據傳輸後安排斷開連接。這大概是80%的時間,而不是所有的時間。至於調試器,它會在disconnectWithErrorOnNetworkThread調用中暫停,然後等待。也實際disconnectWithErrorOnNetworkThread方法永遠不會進入(我有一個NSLog在該方法的開始,永遠不會被調用)。 –

+2

我認爲@Joe詢問目標線程('nThread')發生了什麼,而不是在調用線程中發生了什麼。如果目標線程永遠不會回到它的主循環,它永遠不會爲您執行選擇器。 – abarnert

回答

3

那先掛,如果:

  • 它正試圖在同一個線程的方法是從

  • 調用調用以執行選擇執行一個選擇就是一個線程從同步調用有人提出,引發了執行選擇

當你的程序被掛起,看看所有線程的回溯。

請注意,當實現任何類型的網絡併發時,通常真的很差有從網絡代碼到UI層或其他線程的同步調用。網絡線程需要非常靈敏,因此,就像阻塞主線程是不好的,任何可以阻塞網絡線程的東西都是不好的。

還要注意,一些帶回調的API不一定能保證回調將被傳遞到哪個線程。如上所述,這可能會導致間歇性鎖定。

最後,不要做任何活動的輪詢。你的網絡線程應該完全靜止,除非有事件發生。任何類型的循環輪詢對於電池壽命和響應都是不利的。

+0

你說如果「它試圖在調用方法的同一個線程上執行一個選擇器」,就會發生掛起。但是文檔說:「如果當前線程和目標線程相同,並且您爲此參數指定'YES',則選擇器立即在當前線程上執行」,根據我的經驗,我發現這是真的。 –

+0

是正確的,但並非所有的同步調用機制都可以保護您免受這樣的掛起。例如,'dispatch_sync()'。例如,當以特定模式進行調度時,您也可以掛起嵌套運行循環。 – bbum

+0

@Joe,你有第一個正確的答案,但是SO不讓我把你的評論標記爲答案,所以提高你的評價。 bbum:你的答案更全面,正如你猜測的那樣,主線程阻塞了網絡線程(開始時這真是個壞主意),反之亦然。這是一個簡單的修復。感謝你們兩位的幫助! –

相關問題