当应用程序返回前台时,子线程随机被杀死

时间:2011-08-30 18:28:46

标签: iphone objective-c ios multithreading

据我所知,当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);
}

3 个答案:

答案 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中的某些内容可能会引发异常。如果是这种情况,则断点将立即触发,并且您将拥有一个完整的调用堆栈,其中抛出异常。