Есть ли способ приостановить NSTHread на неопределенный срок и возобновить его из другого потока? - PullRequest
5 голосов
/ 05 августа 2009

Кажется, что это единственный способ уложить NSThread в сон

* sleepForTimeInterval:

* sleepUntilDate:

Было бы плохой практикой то, что я спрашиваю?

Ответы [ 3 ]

17 голосов
/ 05 августа 2009

Вы хотите, чтобы ваш поток просто остановился, пока какой-нибудь другой поток не скажет, что он снова запустится? Если это так, вы можете использовать NSConditionLock. NSConditionLock похож на условную переменную. У него есть несколько основных методов, lockWhenCondition и unlockWithCondition, и lock. Типичное использование состоит в том, чтобы ваш фоновый поток ожидал блокировки условия с помощью «lockWhenCondition:», а внутренний поток - для установки условия, которое вызывает пробуждение фонового потока. Условие является простым целым числом, обычно перечислением.

Вот пример:

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];
}

В этом примере, когда startDoingWork называется doBackgroundWork: запускается в фоновом потоке, но затем останавливается, потому что не нужно выполнять никаких действий. После вызова notifyBackgroundThreadAboutNewWork doBackgroundWork: запустит и обработает новую работу, а затем вернется в спящий режим в ожидании доступности новой работы, что произойдет при следующем вызове notifyBackgroundThreadAboutNewWork.

2 голосов
/ 05 августа 2009

Если у вас действительно есть задачи, которые нужно выполнить в фоновом потоке, но одну задачу необходимо выполнить еще до того, как она выполнится, я бы рекомендовал взглянуть на NSOperation и NSOperationQueue. NSOperation поддерживает установку очень сложных зависимостей, а NSOperationQueue будет обрабатывать планирование и выполнение этих операций в любом подходящем фоновом потоке в правильном порядке. документация Apple по ним довольно хороша, и у Дрю МакКормака есть хорошая статья на эту тему в MacResearch.

0 голосов
/ 05 августа 2009

Не ясно, что вы хотите сделать. Остановить поток и возобновить ту же функцию в новом потоке? (Это было бы бессмысленно - что не так со старым потоком?) Остановить поток и возобновить ту же функцию в другом существующем потоке?

В любом случае, нет, это невозможно, и это даже не хорошая идея. Правильное решение - разделить вашу функцию на две части, а затем использовать некоторые или все циклы выполнения, NSTimer, методы performSelector… и NSPort для достижения того, что вы хотите сделать.

Ваша программа будет работать намного лучше, без всякой магии темных нитей, которую вы себе представляете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...