Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

is there a way to pause an NSTHread indefinitely and have it resumed from another thread?

Seems these are the only methods to put a NSThread to sleep

* sleepForTimeInterval:

* sleepUntilDate:

Would it be bad practice what I am asking?

like image 617
yan bellavance Avatar asked Aug 05 '09 00:08

yan bellavance


2 Answers

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.

like image 186
Jon Hess Avatar answered Oct 12 '22 00:10

Jon Hess


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.

like image 22
Brad Larson Avatar answered Oct 12 '22 01:10

Brad Larson