NSOperationQueue waitUntillAllOperationsAreFinished блокирует операции

Я создал свой собственный подкласс NSOperation и теперь хочу, чтобы некоторые его экземпляры работали параллельно. Поскольку это параллельная операция, я перезаписал

- (void)start {
    [self willChangeValueForKey:@"isExecuting"];
    isExecuting = YES;
    [self didChangeValueForKey:@"isExecuting"];

    error=NO;
    startedSection=NO;

    // start the task
    [task launch];
}

- (BOOL)isConcurrent {
    return YES;
}

- (BOOL)isExecuting {
    return isExecuting;
}

- (BOOL)isFinished {
    return isFinished;
}

и следующий код выполняется, когда операция завершается:

[self willChangeValueForKey:@"isExecuting"];
[self willChangeValueForKey:@"isFinished"];
isExecuting = NO;
isFinished = YES;
[self didChangeValueForKey:@"isExecuting"];
[self didChangeValueForKey:@"isFinished"];

Когда я добавляю [myQueue waitUntillAllOperationsAreFinished] после добавления операций в myQueue, ни одна из операций даже не запускается! Когда я удаляю [myQueue waitUntillAllOperationsAreFinished], я получаю то, что хочу, за исключением того, что это может привести к некоторым ошибкам из-за вмешательства основного потока в эти операции...


person Nickkk    schedule 27.05.2012    source источник


Ответы (1)


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

person Ken Thomases    schedule 27.05.2012
comment
На самом деле я ничего не реализовал... Разве операция не должна выполняться в новом потоке, отличном от основного? - person Nickkk; 27.05.2012
comment
Вы переопределили -isConcurrent, чтобы вернуть YES. Это означает, что вы берете на себя ответственность за его одновременное выполнение. Вы должны делать это только в том случае, если у вас есть особые требования. Терминология несколько сбивает с толку. Думайте об этом больше как о параллельном == асинхронном, неодновременном == синхронном. Самый простой путь — оставить ваши операции непараллельными/синхронными. В этом случае операция queue организует вызов операции в потоке, которым управляет очередь. Операция будет выполняться параллельно с другими операциями, но синхронно с точки зрения очереди. - person Ken Thomases; 27.05.2012
comment
Проблема в том, что моя операция запускает NSTask, который запускается асинхронно, чтобы получить результат... - person Nickkk; 27.05.2012
comment
Так почему вы сказали, что ничего не реализовали? В любом случае, покажите свой -start метод. Кроме того, вероятно, хорошей идеей будет регистрировать значение из +[NSThread isMainThread] и/или +[NSThread currentThread] в нем и в ожидающем потоке. Я подозреваю, что очередь запускает вашу операцию в потоке, в котором вы ее поставили в очередь. Это означало бы, что NSTask зависит от цикла выполнения этого потока. Если вы затем заблокируете этот поток в -waitUntillAllOperationsAreFinished, вы предотвратите получение уведомлений о завершении задачи и фоновое чтение вывода. - person Ken Thomases; 27.05.2012
comment
Я только что сделал логирование... поток, из которого я выполняю -waitUntillAllOperationsAreFinished, имеет другой адрес, чем потоки самих операций, которые не выполняются в основном потоке ([NSThread isMainThread] возвращает false. - person Nickkk; 27.05.2012
comment
Итак, вызывается метод -start вашей операции? Я предполагаю, что да, так как именно там вы бы зарегистрировали поток. Это говорит о том, что ничто не мешает выполнению операций. Вы уверены, что task не-nil? Попробуйте получить обратную трассировку всех потоков. Вы можете сделать это из отладчика (например, thread apply all bt в gdb) или путем выборки процесса. Посмотрите, какие из них могут быть взаимно заблокированы на другом. Кстати, я вижу, что вы написали с ошибкой -waitUntilAllOperationsAreFinished (и я вас скопировал). Я предполагаю, что это просто опечатка в вашем посте, а не ваш код, верно? - person Ken Thomases; 27.05.2012
comment
Код просто делает то, что должен делать, когда я удаляю -waitUntilAllOperationsAreFinished (извините, я написал с ошибкой). Как только добавляю эту строчку программа зависает... - person Nickkk; 27.05.2012