Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to join threads in Objective C without using delegates/callback?

Is there a clean way of joining threads in Objective C much like "Thread.join" in Java? I found the method performSelector:onThread:withObject:waitUntilDone: but the limitation of this is I can't call the "blocking" on a different line because I want to do something like this:

[dispatch Thread A];
[process something on main thread];
[wait for Thread A to finish before proceeding];

Thank you in advance.

like image 356
Manny Avatar asked Nov 30 '22 18:11

Manny


2 Answers

I'm not aware of any Cocoa API to do this, but it wouldn't be too difficult to do with NSThread, pretty easy to do with a lock, and even easier to do with Grand Central Dispatch.

NSThread

NSThread * otherThread = [[NSThread alloc] initWithTarget:self selector:@selector(methodToPerformInBackground:) object:aParameter];
[otherThread start];

//do some stuff

while ([otherThread isFinished] == NO) {
  usleep(1000);
}
[otherThread release];

NSLock

NSLock * lock = [[NSLock alloc] init];

//initiate the background task, which should immediately lock the lock and unlock when done

//do some stuff

[lock lock]; //this will pause until the background stuff unlocks
[lock unlock];
[lock release];

Grand Central Dispatch

dispatch_group_t myGroup = dispatch_group_create();
dispatch_group_async(myGroup, dispatch_get_global_queue(), ^{
  //stuff to do in the background
});

//do some stuff

dispatch_group_wait(myGroup, DISPATCH_TIME_FOREVER);
dispatch_release(myGroup);
like image 185
Dave DeLong Avatar answered Dec 04 '22 07:12

Dave DeLong


NSConditionLock is the answer to my question, Sorry Dave DeLong, but I cannot use:

  1. "while ([otherThread isFinished] == NO) " -- because I need fast continuous processing and cannot use sleep.

  2. NSLock -- because as you said it "initiate the background task, which should immediately lock the lock and unlock when done", this is not a solution because I tried it and we are not sure if the subthread will execute last before the lock-unlock-release on main thread, I ended up getting random errors.

  3. Grand Central Dispatch --because it's only available in IOS4 and Snow Leopard 10.6, I'm using a lower version.

But your answer gave me the idea and thank you very much for it, so I just "upped" you.

I ended up doing this:

#define T_START 0
#define T_FINISHED 1
-(void) updateVerticalScopeBackground: (id) aParam {   
[lockForThread lock];   
NSAutoreleasePool *pool = [NSAutoreleasePool new];   
//do something
[pool release];   
[lockForThread unlockWithCondition:T_FINISHED];  
}


-(void) sumFunc { 
  lockForThread = [[NSConditionLock alloc]
                                   initWithCondition: T_START];
  NSThread* updateVerticalScope = [[NSThread alloc] initWithTarget:self selector:@selector(updateVerticalScopeBackground:) object:nil];
  [updateVerticalScope start];

  //do some processing

  [lockForThread lockWhenCondition:T_FINISHED];   
  [lockForThread unlockWithCondition:T_FINISHED];   
  [lockForThread release]; 
}
like image 20
Manny Avatar answered Dec 04 '22 06:12

Manny