1

我想了解更多关于objective-c中的线程,所以我做了一个小测试程序,它只会循环并输出它所在的循环迭代。但是,我得到的输出不是我所期望的。我知道为什么,但首先是我的代码:

主文件

#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;
}

#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 之间停止)。此外,如果我切换我的代码,以便在主线程循环之后才调用后台循环,那么它将不会运行任何迭代。这是因为主线程已经完成并且不想等待后台线程运行完成吗?如果是这种情况,有没有办法强制程序继续运行,直到主线程和任何后台线程都完成?

4

2 回答 2

3

这几乎可以肯定是因为您在线程完成之前退出自动释放池的范围,您的main函数在后台线程完成之前返回。尝试sleep(3)在其结束之前添加或其他内容,看看您的后台线程是否完成。

在 Mac OS X 上,一个进程在其所有“前台”线程完成后终止。peformSelectorInBackground:仅创建一个后台线程,因此一旦main返回,您将没有前台线程并且您的进程将终止。

于 2013-04-08T18:47:33.363 回答
3

performSelectorInBackground:...这是因为使用和其他 Objective-C API创建的所有线程都是分离的,因此程序可以终止而无需等待它们完成。从线程编程指南

在应用程序退出时,分离的线程可以立即终止,但可连接的线程不能。[...] 如果您确实想创建可连接的线程,唯一的方法是使用 POSIX 线程...

在这种情况下,您的主线程循环恰好比后台线程完成得早一点,因此后台线程循环不会运行到最后。除了使用 POSIX 线程(不太方便),您还可以使用NSOperationQueue,它可以轻松地让您等待队列中的所有操作完成。

于 2013-04-08T18:50:29.630 回答