我想在objective-c中学习更多关于线程的知识,所以我做了一个小测试程序,它只是循环并输出它所在循环的迭代。 但是,我得到的输出并不是我所期待的。我知道为什么,但首先是我的代码:
的main.m
#import <Foundation/Foundation.h>
#import "Car.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
Car* myCar = [[Car new] autorelease];
[myCar performSelectorInBackground:@selector(LoopAndSay) withObject:nil];
for(int i = 0; i < 100; i++ )
{
NSLog(@"Main loop on %i", i);
}
}
return 0;
}
Car.m
#import "Car.h"
@implementation Car
@synthesize name, model;
-(void) LoopAndSay {
for(int i = 0; i < 100; i++)
{
NSLog(@"Looping for the %i time", i);
}
}
@end
现在,如果我按原样运行它,背景循环有时不会完成(在迭代94和97之间停止)。另外,如果我切换我的代码,以便直到主线程循环之后才调用后台循环,那么它将不会运行任何迭代。 这是因为主线程已完成并且不想等待后台线程运行完成?如果是这种情况,有没有办法强制程序继续运行,直到主线程和任何后台线程都完成为止?
答案 0 :(得分:3)
这几乎可以肯定是因为在线程完成之前退出自动释放池的范围你的main
函数在后台线程完成之前返回。尝试在结束前添加sleep(3)
或其他内容,看看后台线程是否完成。
在Mac OS X上,进程在其所有“前台”线程完成后终止。 peformSelectorInBackground:
只创建一个后台线程,所以一旦main
返回,你就没有前台线程了,你的进程就被终止了。
答案 1 :(得分:3)
这是因为使用performSelectorInBackground:...
和其他Objective-C API创建的所有线程都是分离的,因此程序可以终止而无需等待它们完成。来自Threading Programming Guide:
在应用程序退出时,分离的线程可以立即终止,但是可连接的线程不能。 [...]如果你想创建可连接的线程,唯一的方法是使用POSIX线程...
在这种情况下,您的主线程循环恰好比后台线程更快完成,因此后台线程循环不会一直运行到最后。您也可以使用NSOperationQueue
代替使用POSIX线程(这样不太方便),它可以让您轻松等待队列中的所有操作完成。