如何使用[performSelector:onThread:withObject:waitUntilDone:]?

时间:2014-02-25 18:37:10

标签: objective-c multithreading cocoa nsthread

我尝试将NSThread子类化,以便使用一些数据来操作线程。我想根据doc:

在python中模拟join()
  

join():等到线程终止。这会阻塞调用线程直到   调用join()方法的线程终止

所以我认为使用performSelector:onThread:withObject:waitUntilDone:YES会好的,但它不起作用。它什么都不做,不会退出,就像永远一样。

这是我的代码:

@interface MyClass : NSThread
@property (strong, nonatomic) NSMutableArray *msgQueue;
@property (assign, nonatomic) BOOL stop;
@end

@implementation MyClass

-(id)init
{
    self = [super init];
    if (self) {
        self.msgQueue = [NSMutableArray array];
        self.stop = NO;
        [self start];
        return self;
    }
    return nil;
}

-(void)myRun
{
    while (!self.stop) {
        NSLock *arrayLock = [[NSLock alloc] init];
        [arrayLock lock];
        NSArray *message = [self.msgQueue firstObject];
        [self.msgQueue removeObjectAtIndex:0];
        [arrayLock unlock];
        NSLog(@"%@", message);
        if ([message[0] isEqualToString:@"terminate"]) {
            self.stop = YES;
        }
    }
}

-(void)join
{
    [self performSelector:@selector(myRun) onThread:self withObject:nil waitUntilDone:YES];
}

@end

int main(int argc, const char * argv[])
{

    @autoreleasepool {
        MyClass *a = [[MyClass alloc] init];
        [a.msgQueue addObject:@[@"terminate",@"hello world"]];
        //[a myRun];   // this line works so the myRun method should be good,
        [a join];      // but I want this line work, and I have no idea what the problem is.
    }
    return 0;
}

2 个答案:

答案 0 :(得分:1)

来自Apple关于performSelector:onThread:withObject:waitUntilDone:的文档:

  

此方法使用默认的运行循环模式(即与NSRunLoopCommonModes常量关联的模式)在目标线程的运行循环上对消息进行排队。作为其正常运行循环处理的一部分,目标线程使消息出列(假设它在一个默认的运行循环模式下运行)并调用所需的方法。

您可能从未在线程上启动过运行循环,因此它永远不会执行您的myRun方法,因为它没有执行的运行循环。

至于Merlevede的回答,myRun没有排在与join相同的主题上。在您的主线程上调用了join,而您正在尝试将myRun排入您的辅助线程。所以他的理论不正确。还有Apple关于等待参数的文档:

  

如果当前线程和目标线程相同,并且您为此参数指定了YES,则会立即在当前线程上执行选择器。如果指定NO,则此方法将消息排入线程的运行循环并返回,就像对其他线程一样。然后当前线程必须出列并在有机会时处理该消息。

所以,即使它在同一个线程上,它也不会等待,它会立即执行它,就像你直接调用方法而不是首先使用performSelector:一样。 / p>

答案 1 :(得分:0)

你基本上处于僵局状态。

-(void)join
{
    [self performSelector:@selector(myRun) onThread:self withObject:nil waitUntilDone:YES];
}

join正在等待myRun完成(waitUntilDone标志),但是myRun在与join相同的线程上排队,所以它也在等待{{1}完成。

对于join,您永远不会将当前线程作为线程参数传递。