2016-01-25 70 views
4

我有一個多線程程序,需要一次運行許多可執行文件並等待它們的結果。如何安全地在主線程中使用[NSTask waitUntilExit]?

我在NSOperationQueue中使用[nstask waitUntilExit],它在非主線程上運行(在主線程上運行NSTask完全沒有問題)。

我的程序隨機崩潰或運行到斷言失敗和崩潰堆棧總是指向由waitUntilExit運行runloop,執行各種回調和處理程序,包括 - 恕我直言不正確的志願和bindings updating the UI,這會導致他們在非運行-main thread(這是probably the problem described by Mike Ash

我該如何安全地使用waitUntilExit

這是否是waitUntilExit基本上不可用的問題,還是我需要在使用KVO和IB綁定來防止它們在錯誤的線程上處理時需要做一些特殊的事情(除了在主線程上顯式調度我的回調)運行waitUntilExit

+2

的一個問題是:你爲什麼要使用'-waitUntilExit'?爲什麼不從主線程啓動任務,而是阻止等待它退出,添加一個'NSTaskDidTerminateNotification'的觀察器並在那裏做任何你想做的工作?您將不得不在任務持續期間保持對任務對象的強烈參考,但這很簡單。 –

+0

@KenThomases,因爲同步'NSOperation'比異步更容易管理。通過事件和回調,我的ObjC代碼開始看起來像node.js. – Kornel

回答

3

正如Mike Ash指出的那樣,你不能在隨機循環中調用waitUntilExit。這很方便,但它不起作用。你必須在「這實際上方便嗎?」的計算中包含「不起作用」?

但是,您可以在10.7+版本中使用terminationHandler。它不泵浦runloop,所以不應該造成這個問題。您可以重新waitUntilExit有東西沿着這些路線(未經測試,可能不編譯):

dispatch_group group = dispatch_group_create(); 
dispatch_group_enter(group); 
task.terminationHandler = ^{ dispatch_group_leave(group); }; 
[task launch]; 
dispatch_group_wait(group, DISPATCH_TIME_FOREVER); 
+0

納皮爾再次襲擊,這使我從隨機後臺線程異步操作的所有這些奇怪的崩潰救了我很多麻煩。很高興知道如何在必要時強制同步操作 –

0

硬盤沒有的你在做什麼一般情況下說...

一般來說,你不能從非主線程更新界面。因此,如果您在非主線程中觀察到一些NSTasks的KVO通知並更新了UI,那麼您就錯了。

在這種情況下,你可以在需要時更新UI通過簡單

-[NSObject performSelectorOnMainThread:]; 

或類似的修復情況。

至於我更多恩溶液:

  1. 寫入分離NSOperationQueue與maxConcurentOperationsCount = 1(所以FIFO隊列)和寫的NSOperation的子類,將通過委託方法執行NSTask和更新UI。這樣你就可以控制應用程序中執行任務的數量。 (或者你可能會停止所有這些或其他)

  2. 但高水平的解決方案爲您的問題,我認爲將寫入privileged helper tool。使用這種方法,您將獲得2個主要優點:您的NSTask將在分離的過程中執行,並且您將擁有執行任務的root權限。

我希望我的回答涵蓋您的問題。

+0

我遇到的問題是計劃在主線程*上的回調不會在主線程*上運行,因爲waitUntilExit將它們出列在任何地方。 – Kornel