您好,登錄后才能下訂單哦!
你的線程入口
當啟動線程時,你需要有一些代碼來管理當前線程的狀態,線程創建和執行的內存,還有在線程內部拋出的異常。原因是你新創建的線程會有自己的棧,它和默認的棧是不同的,如圖 6-4。因此,你線程使用的內存和主線程使用的內存是不同的。異常也類似;它只會存儲在你的棧中,并不會返回到主棧和主線程中。
有很多事情你需要記住:
Autorelease pool:管理autorelease對象
ExceptionHandler:管理線程運行過程中發生的異常
RunLoop:創建事件處理代碼
我會討論為什么要實現他們已經如何實現他們。
表格6-3 提供了一個簡短的演示,讓你復習一下創建和配置線程的主要技術,以及他們的優缺點。
Autorelease Pool
在應用的每一個線程中,你應該總是要有一個Autorelease Pool,通過把代碼放在@autorelease中塊中。這個pool會包含所有的autoreleased對象,當線程運行的時候。如果你沒有調用返回一個autoreleased對象的方法,最好還是包含@autorelease,因為系統底層的frameworks和libraries也會創建和返回autoreleased對象。如果你有一個@autorelease,而從沒使用它,一切依然能夠正常運行。
如果你通過Xcode模板創建的應用,你會看到main方法中有下面的代碼:
int main(int argc, char *argv[]) {
@autoreleasepool {
int retVal = UIApplicationMain(argc, argv, nil, nil);
}
return retVal;
}
@autorelease將會處理線程內部所有的autoreleased對象。你可能已經知道,autoreleased對象是
一個你不再使用的,但是你又不想立即釋放的對象。它同樣可以使用類似[NSMutableArray array]這樣的工廠方法來返回一個autorelease對象;。這些對象將在run loop結束時被release。
因此,如果你創建了一個新的線程,確保你的代碼包裹在@autorelease塊中,像這樣:
- (void)myThreadMethod {
@autoreleasepool { // Top-level pool
// Do thread work here.
}
}
ExceptionHandler
在處理線程時,異常是非常重要的。因為每一個線程都有它自己的棧,當發生一個異常時,它將會跟蹤所有的方法直到棧的頂部。這可能導致你的線程停止運行。任何主線程中的exception handler將會被忽略。
下面是一個處理異常的基本代碼:
NSObject *myObject = nil;
@try {
// access to some objects inside an array
myObject = [myArray objectAtIndex:2];
}
@catch ( NSException *e ) {
NSLog(@"Array has fewer than 3 items");
}
@finally {
// clean up code here
}
Run Loop
當你創建一個新的線程后,你有兩種方法來執行它。
在線程內部編寫代碼來執行你的邏輯,直到任務執行完畢,而沒有什么中斷。比如,之前介紹過的從URL現在圖片的代碼。顯然,這是比較簡單的。
當有動態事件發生時,你想要你的線程做出響應。比如監聽網絡上的socket或在某個特定時間觸發的事件。這和第一種情況是不同的,需要你在創建一個新的run loop。
下面是一個簡單的代碼,在一個RunLoop中監聽一個輸入流:
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[iStream setDelegate:self];
[iStream scheduleInRunLoop:runLoop forMode:NSDefaultRunLoopMode];
注意:如果[NSRunLoop currentRunLoop]方法是在一個線程中調用,而不是一個run loop,這個方法創建一個新的run loop。 |
如果你想要在開始運行之前,讓一個run loop來等待一段時間,你可以使用NSTimer:
[NSTimer scheduledTimerWithTimeInterval:2.0target:self
selector:@selector(doStuff)userInfo:nil
repeats:YES];
但是,有些情況你不應該使用RunLoop,比如在主線程中你有事件處理代碼,如NSInputStream或NSTimer工作在一些敏感的任務上,要花費很長的時間才能完成。因為事件處理代碼,像我的這個例子,最終會運行在創建它的線程上,你的線程不能繼續運行其他事件處理代碼,直到舊的事件處理完畢。這對UI主線程是非常有害的,如果你在線程內部創建了timer或input stream run loop。主要的問題是它使得你的UI變得更不靈敏。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。