以下代码创建了一个具有主线程超时和已终止应用程序的场景。我不明白为什么。
此方法由主线程调用,根据堆栈跟踪,此调用不是同步的(它直接从 main.m 触发)。然而,为什么执行需要 20 多秒?这个事件不是只有在计时器触发后才会出队吗?
[fooObj performSelector:@selector(populate) withObject:nil afterDelay:2];
崩溃日志:
已用总 CPU 时间(秒):20.060(用户 20.060,系统 0.000),100% CPU 已用应用程序 CPU 时间(秒):19.438,97% CPU
线程 0 名称:调度队列:com.apple.main-thread 线程 0:0
CoreFoundation 0x3ad408b4 CFArrayGetFirstIndexOfValue + 3481 核心基础 0x3ad46e88 CFRunLoopRemoveTimer + 224
2 核心基础 0x3ad46d00 CFRunLoopTimerInvalidate + 324
3 MyApp 0x00034b94 -[容器清除] (Container.m:147)
4 MyApp 0x000348aa -[容器填充] (Container.m:77)
5 MyApp 0x00034f62 -[BaseContainer 填充] (BaseContainer.m:75)
6 基础 0x35bfaa6a __NSFireDelayedPerform + 446
7 核心基础 0x3add45dc CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION + 12
8 核心基础 0x3add428c __CFRunLoopDoTimer + 268
9 核心基础 0x3add2efc __CFRunLoopRun + 1228 10
10 核心基础 0x3ad45eb8 CFRunLoopRunSpecific + 352
11 核心基础 0x3ad45d44 CFRunLoopRunInMode + 100
12 图形服务 0x391132e6 GSEventRunModal + 70
13 UIKit 0x33f852f4 UIApplicationMain + 1116
14 MyApp 0x000029c6 主 (main.m:14)
这是另一个出于相同原因的崩溃:MT 超时。(从日志看来,线程 0 正在等待释放它自己的互斥锁。死锁或误读日志?)
已用总 CPU 时间(秒):20.060(用户 20.060,系统 0.000),100% CPU 已用应用程序 CPU 时间(秒):18.175,91% CPU
线程 0 名称:调度队列:com.apple.main-thread 线程 0:
0 libsystem_kernel.dylib 0x32af50fc __psynch_mutexwait + 24
1 libsystem_c.dylib 0x35e56124 pthread_mutex_lock + 388
2 核心基础 0x3ad46df8 CFRunLoopRemoveTimer + 80
3 基础 0x35bfaa20 __NSFireDelayedPerform + 372
4 核心基础 0x3add45dc CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION + 12
5 核心基础 0x3add428c __CFRunLoopDoTimer + 268
6 核心基础 0x3add2efc __CFRunLoopRun + 1228
7 核心基础 0x3ad45eb8 CFRunLoopRunSpecific + 352
8 核心基础 0x3ad45d44 CFRunLoopRunInMode + 100
9 图形服务 0x391132e6 GSEventRunModal + 70
10 UIKit 0x33f852f4 UIApplicationMain + 1116
11 空间之心 0x000029c6 主 (main.m:14)
12 空间之心 0x00002980 0x1000 + 6528
编辑:添加了清除和填充的实现。如您所见,没有阻塞调用。
- (void)clear
{
self.m_msdData = [NSMutableData dataWithLength:0];
self.m_maItems = [NSMutableArray arrayWithCapacity:0];
self.m_mdItems = [NSMutableDictionary dictionaryWithCapacity:0];
[m_timer invalidate];
self.m_timer = nil;
self.m_nsUrlConnection = nil;
// zz Don't change the property state, in case an observer is already listening.
m_nState = CS_UNPOPULATED;
}
- (CONTAINER_STATE)populate
{
[self clear];
self.m_timer = [NSTimer scheduledTimerWithTimeInterval:TIME_OUT_SEC
target:self
selector:@selector(timeout)
userInfo:nil
repeats:NO];
self.m_nState = CS_POPULATING;
return CS_POPULATING;
}