2015-07-30 4 views
2

Я хочу построить NSOperation, у которого есть время ожидания 10 секунд после его начала и может быть закончено другим потоком в любой момент через событие. Я также использую NSOperationQueue для управления больше операций, подобных этому, и он может вычислять только один за раз (maxConcurrentOperationCount = 1). Для этого я думал о реализации с использованием dispatch_semaphore «S, как это следующим образом:dispatch_semaphore_wait не запускается после таймаута

@implementation CustomOperation 

dispatch_semaphore_t semaphore; 
-(void) main { 
    @autoreleasepool { 

     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(shouldFinishWaiting:) name:@"myCustomEvent" object:nil]; 

     semaphore = dispatch_semaphore_create(0); 

     [self doStuff]; 

     dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC))); 
     [[NSNotificationCenter defaultCenter] removeObserver:self name:@"myCustomEvent" object:nil]; 
    } 
} 


-(void) shouldFinishWaiting { 
    NSLog(@"[WatchOperation]: Should finish waiting! %@", self); 
    dispatch_semaphore_signal(semaphore); 
} 

@end 

У меня есть проблема в том, что когда-то во много раз, когда пользователь запускает приложение, первая операция не будет конца, пока событие не сработало (и это может произойти через 30 минут). Тайм-аут не принимался во внимание. Я заметил это в журналах от некоторых пользователей, поэтому я не смог воспроизвести его. Что может пойти не так, чтобы dispatch_semaphore_wait не смог выполнить?

Позже редактирование: я ошибочно считал, что -doStuff является асинхронным. Кажется, он not.I заменил его:

dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{ 
    [self doStuff]; 
}); 

, но операция была уже на последовательную очереди "инициированный пользователем. Как я вижу, это создает еще одну совпадающую нить, это произойдет каждый раз? Это безопасно?

+1

Что такое '-doStuff'? Это асинхронно? То есть, он запускает что-то на вторичном потоке или очереди отправки, а затем немедленно возвращается, не дожидаясь завершения чего-либо? Если это синхронно, ваш семафор бесполезен. –

+0

Он асинхронный. Он запускает действие в одном и том же потоке и заканчивается, семафор ждет событие из другого потока. –

+0

ОК, мой плохой ... кажется, что -doStuff был синхронным :( –

ответ

0

Я полагаю, ваш семафор не будет оставаться глобальной переменной ...

В зависимости от того, используете ли вы 32 или 64 бит, NSEC_PER_SEC может быть 32 бит значение, которое разливается и превращается в нечто отрицательное, умноженное на 10. Замените 10 на 10.0. Можете решить проблему, возможно, ничего не получится.

+0

Как видно из журналов, кажется, что в какой-то момент dispatch_semaphore_wait запускает операцию для продолжения, но после гораздо более длительного времени, чем ожидалось –

0

@selector (mustFinishWaiting :) должен быть @selector (shouldFinishWaiting). Нет двоеточия, потому что метод не имеет аргументов.

+0

Спасибо, но это причина: D? –

1

Я не думаю, что семафор отправки может пойти не так. Возможно, ваш -doStuff занимает слишком много времени. Убедитесь, что вы делаете следующее:
1. Метод [self doStuff]; является асинхронным и отправляет его в РАЗЛИЧНЫЙ поток, чем текущий (отправка в текущую нить не имеет смысла, если вы хотите 10-секундный таймаут с использованием семафора) ,
2. Убедитесь, что вы продолжаете проверять наличие self.isCancelled в -doStuff.

Кроме того, я хотел бы предложить вам принять несколько иной подход к проектированию для ваших требований (если я их понимают правильно) -
1. Вашего NSOperation всегда может быть отменен из любой внешней резьбы моих призывающей отменить на объекте, поэтому нет необходимости в сложном подходе, основанном на NSNotification, просто проверьте, isCancelled и переопределить метод -cancel.
2. Для 10-секундного тайм-аута вы можете использовать семафорный подход, но просто иметь РАЗЛИЧНЫЙ поток, выполняющий ожидание семафора. Этот поток может отменить вашу задачу изнутри через 10 секунд.

+0

, пожалуйста, проверьте обновленный ответ –

Смежные вопросы