2013-03-04 36 views
1

以下代碼在iOS模擬器中產生崩潰。GCD與超過255秒的任何任務崩潰

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     NSDate *sleepStart = [NSDate date]; 
     while ([sleepStart timeIntervalSinceNow] > -300) { 

     } 
    });  
} 

更新:即使發生在後臺線程此問題。

下面的代碼也是越野車:

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     NSDate *sleepStart = [NSDate date]; 
     while ([sleepStart timeIntervalSinceNow] > -300) { 

     } 
    });  
} 

這就是全部。將其粘貼到任何視圖控制器中,在模擬器中運行該應用程序正好4分15秒,並且會崩潰。

這次撞車是我從未見過的一種類型。這是「EXC _ ???(11)」。奇怪的是,你可以在崩潰後按下繼續按鈕,它會像平常一樣繼續。

爲什麼會崩潰?如何將長期任務提交給隊列而不會導致此行爲?

這裏有一些事情到目前爲止,我已經試過了,已經擺脫無光任何的奧祕:

  • 創建我自己的調度隊列(包括後臺線程的)
  • 使用NSBlockOperation代替的GCD(仍然崩潰)
  • 插入睡眠。短時間睡眠(5秒左右)似乎可以延緩睡眠時的崩潰。更長的睡眠似乎做了更多。所以如果你一次睡五秒鐘,它將會以4米20秒的速度而不是4米15秒的速度崩潰。如果你一次睡60秒,大概需要十分鐘才能崩潰,但最終會發生。這個線索似乎很重要,但我不知道它可能意味着什麼。

更新#1

的問題僅LLDB,不GDB下再現。

+3

你舉起了主線?是的,它會崩潰。 – 2013-03-04 03:38:23

+2

爲了擴大這個範圍:iOS發現你的應用一直沒有響應(對任何事件沒有響應)時間過長,並且因爲這意味着你的應用被破壞,它會殺死你的應用。你不應該超過1/60秒,更不用說4分鐘了。爲什麼不在一個併發隊列中運行此塊? – 2013-03-04 03:42:59

+0

問題更新後,行爲與主隊列是否被阻止或後臺隊列無關。 – Drew 2013-03-04 05:29:28

回答

2

Apple engineer

的「崩潰」你看到的是不是真的崩潰,其日誌時 應用程序使用太多CPU時間持續一段時間。它的 存在的理由是告訴你不要這樣做,並且CPU時間 正在花費。在生產中,日誌會被簡單地記錄下來,並且您的過程應該繼續。但是如果你能避免這些類型的日誌,那就更好了。

及更高版本:

您應該提交錯誤報告。 lldb應該足夠聰明以默認忽略該陷阱。

4

您不能在主線程上執行冗長的操作。您應該將塊分派給另一個線程,然後在塊的末尾派送回主線程(如果需要的話)。

使用dispatch_async(dispatch_get_main_queue(),^{});會導致您的操作在不久的將來在主線程上執行(阻塞)。

主線程受計時器保護;如果你停止響應事件,iOS會終止它。這是故意的:不要在主線上舉重!

iOS的容忍度通常是,遠遠低於4分鐘的,但如果您正在調試,它會變得更長。模擬器有其自己的規則。

在啓動時,這只是幾秒鐘的事情。但是你不應該在主線程上花費不止一秒的時間,而只是在直接用戶操作(例如用戶點擊某件事)時做出響應。在主線程上工作會導致iOS界面變得不太靈敏,而不是平滑。

如果您的應用程序停止響應OSX上主線程上的事件,它就是沙灘球。你的應用停止響應iOS上主線程的事件,iOS看門狗將它取出並拍攝。

TechNote TN2151

異常代碼0x8badf00d指出一個應用程序已經被終止的iOS因爲看門狗超時發生。應用程序花費太長時間才能啓動,終止或響應系統事件。其中一個常見原因是在主線程上進行同步聯網。無論線程0上的操作如何:需要移動到後臺線程,或者以不同的方式處理,以便它不會阻塞主線程。

一般來說,模式是:

- (IBAction)tappedWhatever:(id)sender { 
    // visually start operation 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^{ 
     // do work here, off main thread 
     // (you can't update the UI here) 
     dispatch_async(dispatch_get_main_queue(),^{ 
      // show progress in UI 
     }); 
     // more heavy lifting 
     dispatch_async(dispatch_get_main_queue(),^{ 
      // update UI to show operation complete and move to next step 
     }); 
    }); 
}; 

(?我可以發誓,有這個蘋果的文檔更好的說明,但現在我找不到它的任何人)

+0

有趣的是「沙灘球」官方術語xD?我一直把它稱爲「死亡的糖果輪」 – borrrden 2013-03-04 03:48:49

+0

我一直很喜歡旋轉比薩,但沙灘球似乎贏了。 :) – 2013-03-04 03:49:28

+1

「我很驚訝超時設置了這麼長時間」 - 也許是因爲他正在模擬器中嘗試它?在設備上,看門狗應該在10秒內殺死他。 – matt 2013-03-04 03:54:25