这里只是分享一下,我在写一个处理线程时遇到的问题以及处理方法。
由于各种原因,处理线程需要在主线程启动后,就启动。
而这个线程需要在当前类被释放后,而在外部要停止一个线程也不是那么容易,最好让其自动停止,所以当这个线程启动后,就直接一个while循环中,通过一个条件变量来控制这个这个线程的正常寿终与否。当主线程要这个线程停止时, 就更改这个while中的变量即可。如果主线程只是想要这个子线程暂时停止处理时,可以通过变量decodeIsHandling来进行控制.
// 这里还要说的是这个NSAutoreleasePool, 首先,遵循苹果的原则, 线程起初加入建立一个autoreleasePool, 线程最后一句加入autoreleasePool release。
由于线程主要在while中的else中执行代码,所以需要在这个else中添另一个autoreleasePool以便及时释放临时内存,之前我没有在这个else之中加入autoreleasePool,所以导致这里面的自动释放的内存一直得不到释放,而导致运行30分钟左右,出现系统紧急错误而崩溃,原因就是只有当这个while停止时, 这批自动释放的对象才能得到释放,而要这个while停止时,一般就是程序即出时需要做的操作。
另外一点是, 在子线程中要更改主线程的界面操作, 一定需要调用performSelectorOnMainThread才能做到。没其它办法。
我尝试在子线程中抛出Notification对象,给主线程,主线程再根据notification中的数据来显示,结果发现主线程确实收到这个notificaiton,并取得notification的对象数据,但就是显示不出来,或者说是只显示最后一次调用notification时的界面绘制。
所以切记。
上代码,各位看官可自行分析。
- (void)frameDecodeThread {
NSAutoreleasePool *decodeThreadPool = [[NSAutoreleasePoolalloc]init];
while (decodeThreadShouldRun) {
if (decodeIsHandling == NO) {
// 空转等待开始处理
usleep(DEFAULTEMPTYRUNLOOP *1000);
NSLog(@"Empty run in while roop");
continue;
}else {
NSAutoreleasePool *whilePool = [[NSAutoreleasePoolalloc]init];
// 处理一个,先判断条件是否满足,如果
NSDictionary mediaDic = /..判断处理前提../
//表示里面没有数据,等待缓冲
if (mediaDic == nil) { // 睡默认时间
curTime = [NSDatetimeIntervalSinceReferenceDate];
// curTime-lastTime相减得到的值是以秒为单位,而这里进行计算均是按毫秒计算的,usleep是以微秒计算
if ((DEFAULTFRAMEINTERVAL <= (curTime-lastTime)*1000)) {
// 表示已经超时,直接到下一个循环
}else {
usleep((DEFAULTFRAMEINTERVAL - (curTime-lastTime)*1000) *1000);
}
NSLog(@"wait for data . in caching...");
}else {
NSData *fullPurePacketData = (NSData *)[mediaDicobjectForKey:C_FULLPACKETDATA];
UIImage *showImage = [videoPlayStream decodeWithMediaPureData:fullPurePacketData];
// NSLog(@"after decodeWithMediaPureData:%@", [dateFormatter stringFromDate:[NSDate date]]);
if (showImage == nil) {
//不做continue, 在结尾处可以使得mediaDic被释放
}else {
curTime = [NSDatetimeIntervalSinceReferenceDate];
usleep((playInterval -MICROSECONDSFORPLAYCACHE - (curTime-lastTime)*1000) *1000);// 等待缓冲状态
[selfperformSelectorOnMainThread:@selector(OriginimageArrival:)withObject:showImagewaitUntilDone:YES];
}
//记录这帧的时间戳,以及这帧的播放时间点作为下次参照依据,作为上次刷屏时间
lastTime = [NSDatetimeIntervalSinceReferenceDate];
lastFrameTimeStamp = purePacketTimeStamp;
[mediaDicrelease];
}
[whilePoolrelease];
}
}
[videoPlayStreamrelease];
[decodeThreadPoolrelease];
}
<smking:现在看来, 这段代码应该改成 NSRunloop的方式来使用, 就会降低CPU的时间片消耗>