I tried to subclass NSThread in order to operate a thread with some data. I want to simulate the join() in python, according to the doc:
join(): Wait until the thread terminates. This blocks the calling thread until the thread whose join() method is called terminates
So I think using performSelector: onThread: withObject: waitUntilDone:YES would be fine, but it does not work. It just do nothing and would not exit, running like forever.
This is my code:
@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;
}
From Apple's documentation on performSelector:onThread:withObject:waitUntilDone::
This method queues the message on the run loop of the target thread using the default run loop modes—that is, the modes associated with the NSRunLoopCommonModes constant. As part of its normal run loop processing, the target thread dequeues the message (assuming it is running in one of the default run loop modes) and invokes the desired method.
You probably never started a run loop on the thread, so it will never execute your myRun method, since it has no run loop to execute on.
As for Merlevede's answer, myRun is not enqueued on the same thread as join. join was called on your main thread, whereas you're trying to enqueue myRun on your secondary thread. So his theory is incorrect. Also from Apple's documentation regarding the wait parameter:
If the current thread and target thread are the same, and you specify YES for this parameter, the selector is performed immediately on the current thread. If you specify NO, this method queues the message on the thread’s run loop and returns, just like it does for other threads. The current thread must then dequeue and process the message when it has an opportunity to do so.
So even if it was on the same thread, it wouldn't be stuck waiting, it would just execute it right away as if you had directly called the method instead of using performSelector: in the first place.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With