据我所知,当iOS应用程序进入后台时,所有子线程都被置于保持状态。我的问题是为什么操作系统会杀死一个子线程(随机)?有时当应用程序返回到前台时,它工作正常,但有时候子线程被杀死。
这是我创建子线程的方式:
NSOperationQueue *queue = [NSOperationQueue new];
NSInvocationOperation *operation = [[NSInvocationOperation alloc]
initWithTarget:self
selector:@selector(syncTimerRunning)
object:nil];
[queue addOperation:operation];
[operation release];
*更新*
更改代码如下,希望进一步调试。
self.queue = [NSOperationQueue new];
self.operation = [[NSInvocationOperation alloc]
initWithTarget:self
selector:@selector(syncTimerRunning)
object:nil];
[self.queue addOperation:self.operation];
//[operation release];
同时检查我的一个NSTimer循环中的以下内容,以检查线程是否被杀死。
if([self.queue isSuspended]) {
NSLog(@"queue is suspended");
}
if([self.operation isCancelled]) {
NSLog(@"operation is cancelled");
}
if([self.operation isFinished]) {
NSLog(@"operation is finished");
}
在评论出[operation release]
并将其作为类属性之后,我还无法重现这个问题,该类属性在类发布时会被释放。
*另一次更新*
我的印象是,当您向队列添加操作时,它会将其保留在内存中,因此操作释放实际上不是原因。仍在尝试在更改后重现问题。
*和另一次更新*
好吧,我能够再次重现它,并吐出operation is finished
,所以[self.operation isFinished]
是真的。我不明白它是如何或为什么触发它完成时,显然不是。我有一个NSLog应该在子线程完成之前触发 - 这是syncTimerRunning
方法。
- (void) syncTimerRunning
{
while (self.secondsCount > 0) {
// need to query the server and get the current running timer and update the seconds
TimeboxedEvent *te2 = [TimeboxedEvent getTimeboxedEvent:self.agentProfileId andIsPlayer:((self.gift == nil) ? YES : NO)];
long timeLeft = (self.timeboxedEvent.timeBoxedEventTotalSeconds - (([te2.timeBoxedEventCurrentTimestamp longLongValue] - [te2.timeBoxedEventBeginTimestamp longLongValue]) / 1000));
NSLog(@"retreived timebox: %@ - current time: %@ - time left: %ld - current seconds: %i", te2.timeBoxedEventBeginTimestamp, te2.timeBoxedEventCurrentTimestamp, timeLeft, self.secondsCount);
if (timeLeft >= 0) {
self.secondsCount = timeLeft;
} else {
self.secondsCount = 0;
}
sleep(10.0f);
}
NSLog(@"seconds count: %i", self.secondsCount);
}
答案 0 :(得分:1)
你是什么意思被“杀死”,为什么你认为它正在发生?确认您的应用程序在您进入后台和进入前台之间没有终止。如果您被停职,您将不会收到有关您被终止的通知。
syncTimerRunning
可以以什么方式终止?它更可能是这样做(可能是为了响应意外错误),而不是OS正在杀死应用程序中的一个线程。
修改强>
你被“杀死”是什么意思。你是说你相信pthread_cancel()
被称为(为什么你相信?)或者你的意思是“我的NSLog()条目似乎不再出现了?”
当你说“应用程序回来后”你的意思是“线程在applicationWillEnterForground:
之后继续运行一段时间,然后我不再看到它正在运行”或“你的意思是”它似乎永远不会出现再次运行?”附加调试器并检查堆栈时线程是否仍然存在?线程处于什么状态?
发生这种情况时队列中的哪些操作? NSOperation
对象会消失吗?如果没有,它处于什么状态?它是标记为isCancelled
还是isFinished
?
答案 1 :(得分:1)
好吧,我发现了问题。
这条线偶尔失败了:
TimeboxedEvent *te2 = [TimeboxedEvent getTimeboxedEvent:self.agentProfileId andIsPlayer:((self.gift == nil) ? YES : NO)];
失败后,它会自动终止该主题,这就是为什么它将isFinished
设置为YES
。
失败了,因为手机偶尔会丢失互联网连接,这是进行同步所必需的。我在调用getTimeboxedEvent之前添加了一个互联网检查,然后瞧。
答案 2 :(得分:0)
在这种情况下,最好在调试器中运行程序并创建“异常断点”。你NSOperation
中的某些内容可能会引发异常。如果是这种情况,则断点将立即触发,并且您将拥有一个完整的调用堆栈,其中抛出异常。