2011-06-14 46 views
4

我正在創建一個NSTimer並將其添加到後臺線程的runloop。 我的代碼是像該答案後臺線程例如:iPhone-SDK:Call a function in the background?NSTimer無效後,後臺線程NSRunloop運行不會退出!爲什麼?

創建計時器,它從GDB attching到runloop後我po runLoop並輸出這樣的:

<CFRunLoop 0x695b090 [0x16a62c0]>{wakeup port = 0x6907, stopped = false, 
current mode = kCFRunLoopDefaultMode, 
common modes = <CFBasicHash 0x6936e60 [0x16a62c0]>{type = mutable set, count = 1, 
entries => 
    1 : <CFString 0x16abba8 [0x16a62c0]>{contents = "kCFRunLoopDefaultMode"} 
} 
, 
common mode items = <CFBasicHash 0x695e160 [0x16a62c0]>{type = mutable set, count = 1, 
entries => 
    0 : <CFRunLoopTimer 0x69398a0 [0x16a62c0]>{valid = Yes, interval = 6, next fire date = 329774303, callout = __NSFireTimer (0x212399), context = <CFRunLoopTimer context 0x6903a10>} 
} 
, 
modes = <CFBasicHash 0x6904120 [0x16a62c0]>{type = mutable set, count = 1, 
entries => 
    1 : <CFRunLoopMode 0x6946180 [0x16a62c0]>{name = kCFRunLoopDefaultMode, port set = 0x6807, timer port = 0x6b03, 
    sources0 = (null), 
    sources1 = (null), 
    observers = (null), 
    timers = <CFArray 0x695e180 [0x16a62c0]>{type = mutable-small, count = 1, values = (
    0 : <CFRunLoopTimer 0x69398a0 [0x16a62c0]>{valid = Yes, interval = 6, next fire date = 329774303, callout = __NSFireTimer (0x212399), context = <CFRunLoopTimer context 0x6903a10>} 
)} 
}, 

} 
} 

這表明1個定時器連接到runloop 後來經過我的無效計時器NSRunloop run方法不退出,但之後我暫停調試器和GDB從我po runLoop再次,它看起來是這樣的:

<CFRunLoop 0x695b090 [0x16a62c0]>{wakeup port = 0x6907, stopped = false, 
current mode = kCFRunLoopDefaultMode, 
common modes = <CFBasicHash 0x6936e60 [0x16a62c0]>{type = mutable set, count = 1, 
entries => 
    1 : <CFString 0x16abba8 [0x16a62c0]>{contents = "kCFRunLoopDefaultMode"} 
} 
, 
common mode items = <CFBasicHash 0x695e160 [0x16a62c0]>{type = mutable set, count = 0, 
entries => 
} 
, 
modes = <CFBasicHash 0x6904120 [0x16a62c0]>{type = mutable set, count = 1, 
entries => 
    1 : <CFRunLoopMode 0x6946180 [0x16a62c0]>{name = kCFRunLoopDefaultMode, port set = 0x6807, timer port = 0x6b03, 
    sources0 = (null), 
    sources1 = (null), 
    observers = (null), 
    timers = <CFArray 0x695e180 [0x16a62c0]>{type = mutable-small, count = 0, values =()} 
}, 

} 
} 

現在「計時器」條目有0個對象。但線程繼續運行。我經常離開屏幕然後回來,所以這導致建立後臺線程,在使用太多資源後最終會終止應用程序。定時器在失效後不會觸發,但後臺線程保持不變。

我知道我可以將定時器移回主線程或使用NSThread sleepForTimeInterval創建我自己的簡單定時器線程,但我想保留GUI更新的主線程並儘可能使用NSTimer。

回答

1

-[NSRunLoop run]文檔:

手動從運行循環中刪除所有已知的輸入源和定時器是不能保證運行退出循環。

您應該在循環中使用不同的方法,可能是runMode:beforeDate:,並且同時使計時器無效,請設置一個標誌指示運行循環應該結束。

0

我需要閱讀[NSTimer invalidate]的文檔....此方法必須從安裝了該定時器的相同線程中調用。如果你不從同一個線程調用它,計時器線程將不會退出。

1

這將停止運行循環對我罰款:

[[NSRunLoop currentRunLoop] runUntilDate: [NSDate date]];

如果你正在編寫可以在主線程上運行的代碼(因此使用主runloop)雖然,你應該檢查看看你目前的runloop是否是主要的runloop之前 - 否則你會炸燬你的應用程序。

// Kill the runloop now. 
NSRunLoop* rl = [NSRunLoop currentRunLoop]; // Get the runloop 
if (rl != [NSRunLoop mainRunLoop]) 
{ 
    // Set it running again, but only until now. 
    // In other words, STOP!!! 
    [rl runUntilDate: [NSDate date]]; 
}