2012-06-08 15 views
16

我們可以有許多處理程序:觸摸處理程序,UIControl處理程序(按鈕,滑塊),performSelector,CADisplayLink,NSTimer事件,手勢識別器,加速度計處理程序和UIView動畫完成塊以及其他一些。iOS應用程序中的所有方法通常在單個線程中嗎? (用於競賽狀態預防)

他們都在同一個線程?也就是說,只有其中一個可以同時運行?

一些其他方法或處理程序是否可以成爲另一個線程的一部分,因此可以創建競爭條件?

+1

+1個不錯的問題 –

回答

16

通常,你會發現iOS上最簡單的應用程序傾向於在主線程上執行幾乎所有的操作。正如您所指出的那樣,當您將多線程添加到圖片中時,您會添加另一組棘手的問題以提醒您注意。許多開發人員不想爲此增加複雜性而煩惱,或者不熟悉GCD或線程,因此他們避免在後臺線程或GCD隊列中執行任何操作。

你在問題中列出的幾個項目涉及到與UIKit的交互,並且通常這些交互必須發生在主線程上(儘管iOS 4.x增加了在後臺執行一些繪圖功能的能力)。您在主線程上收到觸摸和其他相關事件。如果你想更新界面的大部分內容,那麼安全的方法是在主線程上執行這些更新。

定時器(NSTimer,CADisplayLink)可以通過將它們附加到在後臺線程上運行的NSRunLoop來在後臺線程上觸發它們的更新。你很少看到人們這樣做,但它可以做到。通常,人們在主運行循環上配置定時器,這會導致在主線程上傳遞迴調。

當執行動畫時,動畫本身將在後臺線程上運行(您看到它們不會停止,而用其他方法阻止主線程),但幾乎總是會收到完成塊或當主線程完成時回調。如果我沒有記錯的話,這裏有一兩個例外,它們在蘋果的文檔中被記錄下來。在處理可能不知道幕後發生的開發人員處理主線程時觸發這些回調是安全的。

所有這一切說,有很多理由想要添加多線程到您的應用程序。因爲所有的用戶界面更新和觸摸交互發生在主線程上,如果你有一些計算成本昂貴或者只是需要花費很多時間來執行的情況,如果你在主線程上運行它,你似乎會凍結你的應用。這是一種糟糕的用戶體驗,因此您希望將此任務移至後臺線程,以便用戶在進行此操作時可以繼續與應用程序進行交互。此外,越來越多的iOS設備每天都會運行多個內核,並且平衡您在這些內核之間的工作負載,並且在使用此硬件時效率更高,這需要一定程度的併發處理。

在編寫代碼多線程時,人們已經寫了關於最佳實踐的書籍,在這裏可以找到很多關於此的問題,所以我不會詳細討論。我可以告訴你的是,你應該閱讀蘋果的Concurrency Programming Guide並觀看過去兩年與大中央調度相關的WWDC視頻。藉助GCD,Apple以高效且(相對)安全的方式爲您的應用程序添加多線程變得更容易,我鼓勵您爲自己的應用程序研究這一點。

例如,我有一個開源的iOS應用程序,執行詳細的分子結構渲染。我在背景GCD隊列上渲染每個幀,因爲有時它們會花費1/60秒以上的時間來處理,在這種情況下,如果全部在主線程上,它們會導致觸摸事件被刪除,並且接口會斷斷續續。此外,在新型多核設備上運行時,我看到這樣做的性能提高了40%。爲了避免競爭條件,我使用串行調度隊列中的共享數據結構和上下文進行交互,以便無論某個特定塊在哪個線程上運行,一次只能有一個動作使用資源。這隻需要添加幾行代碼,但性能和用戶體驗的好處是巨大的。

相關問題