Seems these are the only methods to put a NSThread to sleep
* sleepForTimeInterval:
* sleepUntilDate:
Would it be bad practice what I am asking?
Seems these are the only methods to put a NSThread to sleep
* sleepForTimeInterval:
* sleepUntilDate:
Would it be bad practice what I am asking?
It's not clear what you want to do. Stop the thread and resume the same function on a new thread? (That would be pointless—what was wrong with the old thread?) Stop the thread and resume the same function on another existing thread?
Either way, no, it's not possible, and it's not even a good idea. The correct solution is to split your function in two, then use some or all of the run loop, NSTimer, the performSelector…
methods, and NSPort to achieve whatever it is you want to do.
Your program will work much better without all this dark thread magic going on that you're envisioning.
Do you want your thread to just stop until some other thread tells it to start up again? If so, you could use an NSConditionLock. An NSConditionLock is similar to a condition variable. It has a couple of basic methods, lockWhenCondition, and unlockWithCondition, and lock. A typical usage is to have your background thread waiting on the condition lock with "lockWhenCondition:", and the in you foreground thread to set the condition, which causes the background thread to wake up. The condition is a simple integer, usually an enumeration.
Here's an example:
enum {
kWorkTodo = 1,
kNoWorkTodo = 0
}
- (id)init {
if ((self = [super init])) {
theConditionLock = [[NSCoditionLock alloc] initWithCondition: kNoWorkTodo];
workItems = [[NSMutableArray alloc] init];
}
}
- (void)startDoingWork {
[NSThread detachNewThreadSelector:@selector(doBackgroundWork) toTarget:self withObject:nil];
}
- (void)doBackgroundWork:(id)arg {
while (YES) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSArray *items = nil;
[theConditionLock lockWhenCondition:kWorkTodo]; // Wait until there is work to do
items = [NSArray arrayWithArray:workItems]
[workItems removeAllObjects];
[theConditionLock unlockWithCondition:kNoWorkTodo];
for(id item in items) {
// Do some work on item.
}
[pool drain];
}
}
- (void)notifyBackgroundThreadAboutNewWork {
[theConditionLock lock];
[workItems addObject:/* some unit of work */];
[theConditionLock unlockWithCondition:kWorkTodo];
}
In this example, when startDoingWork is called doBackgroundWork: will start on a background thread, but then stop because there isn't any work to do. Once notifyBackgroundThreadAboutNewWork is called, then doBackgroundWork: will fire up and process the new work, and then go back to sleep waiting for new work to be available, which will happen the next time notifyBackgroundThreadAboutNewWork is called.
If you really do have tasks that you need to execute on a background thread, yet one task needs for another to be completed before it executes, I'd recommend looking at NSOperation and NSOperationQueue. NSOperation supports setting very complex dependencies, and NSOperationQueue will handle the scheduling and execution of those operations on however many background threads are appropriate, in the right order. Apple's documentation on these is pretty good, and Drew McCormack has a nice article about the topic at MacResearch.