以下代码在 iOS 模拟器中产生崩溃。
- (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) {
}
});
}
就这样。将其粘贴到任何 View Controller 中,在模拟器中运行该应用程序正好 4 分 15 秒,它就会崩溃。
崩溃是我以前从未见过的类型。它是“EXC_??? (11)”。奇怪的是,您可以在崩溃后按下继续按钮,它会像往常一样继续。
为什么会崩溃?如何在不导致此行为的情况下将长任务提交到队列?
以下是我迄今为止尝试过的一些事情,但对这个谜团没有任何启示:
更新 #1
该问题仅在 LLDB 下重现,而不在 GDB 下重现。
最佳答案
您不能在主线程上执行冗长的操作。您应该将 block 分派(dispatch)到另一个线程,然后在 block 分派(dispatch)结束时返回主线程(如果需要)。
使用 dispatch_async(dispatch_get_main_queue(),^{});
导致您的操作在不久的将来在主线程上执行(阻塞)。
主线程受定时器保护;如果你停止响应事件,iOS 会杀死它。这是故意的:不要在主线程上做繁重的工作!
iOS 的容忍度通常远少于四分钟,但如果你在调试,它会变得更长。模拟器有自己的规则。
启动时,只需几秒钟。但是你不应该在主线程上做任何事情超过一瞬间,然后才能响应直接的用户操作(例如用户点击某物)。在主线程上工作会导致 iOS 用户界面变得 react 迟钝、生涩而不是玻璃般光滑。
如果您的应用程序停止响应 OSX 上的主线程上的事件,它就会成为沙滩球。您的应用程序停止响应 iOS 上主线程上的事件,iOS 看门狗将其取出并射击。
来自 TechNote TN2151 :
The exception code 0x8badf00d indicates that an application has been terminated by iOS because a watchdog timeout occurred. The application took too long to launch, terminate, or respond to system events. One common cause of this is doing synchronous networking on the main thread. Whatever operation is on Thread 0: needs to be moved to a background thread, or processed differently, so that it does not block the main thread.
一般来说,模式是:
- (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
});
});
};
(我本可以发誓在 Apple 的文档中对此有更好的描述,但我现在找不到。有人吗?)
关于ios - 任何超过 255 秒的任务都会导致 GCD 崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15194163/