NSOperationQueue queue waitUntilAllOperationsAreFinished зависает - PullRequest
1 голос
/ 29 июля 2010

У меня есть приложение для iphone, в котором при загрузке контроллера представления я хочу вызвать веб-сервис, получить и проанализировать все XML в фоновом потоке.Затем обновите пользовательский интерфейс после завершения потока, затем запустите другой поток, чтобы выполнить вторую операцию в другом фоновом потоке.

В некотором роде цепочечные вызовы потоков:

  1. Поток пользовательского интерфейса -> Создать BG-поток
  2. BG-поток -> Позвонить в службу XML и получить результаты
  3. UI-поток -> Обновить пользовательский интерфейс успешного выполнения операции BG-потока
  4. BG-поток ->Запустите часть 2 операции

Все при загрузке приложения.

Проблема в том, что моя первая операция BG Thread никогда не заканчивается.Я добавил вызов waitUntilAllOperationsAreFinished после выполнения шага 2, просто чтобы посмотреть, что происходит, и мое приложение, похоже, никогда не достигнет этой точки.

Это своего рода базовая реализация скелета:

- (void) viewDidLoad 
{
    queue = [[NSOperationQueue alloc] init];
[queue setMaxConcurrentOperationCount:1];

    //other stuff

    [self loadFriendsInBackgroundThread];
}

- (void) loadFriendsInBackgroundThread
{   
    NSInvocationOperation *operation = [NSInvocationOperation alloc];
    operation = [operation initWithTarget:self selector:@selector(invokeLoadingOfFriends:) object: nil];

    [queue addOperation:operation];
[operation release];
}

- (void) invokeLoadingOfFriends: (id) obj
{
    //webservice calls and results

    [self performSelectorOnMainThread:@selector(invokeRefreshAfterLoadingFriends:) 
                       withObject:nil 
                    waitUntilDone:YES];
}

- (void) invokeRefreshAfterLoadingFriends: (id) obj
{
    //this line is where is hangs
    [queue waitUntilAllOperationsAreFinished];

    //never gets here
    [self refresh: NO];
}

Есть идеи, почему первый вызов потока никогда не заканчивается?

Спасибо за любую помощь, которую вы можете оказать Марку

1 Ответ

2 голосов
/ 29 июля 2010

Здесь вы вызываете метод в главном потоке, который ожидает завершения вызванного метода (waitUntilDone:YES):

[self performSelectorOnMainThread:@selector(invokeRefreshAfterLoadingFriends:) 
                   withObject:nil 
                waitUntilDone:YES];

Затем вы вызываете -invokeRefreshAfterLoadingFriends:, который удерживает основной поток до завершения операции, поэтому метод никогда не будет "завершен". Из документации на -waitUntilAllOperationsAreFinished:

При вызове этот метод блокирует текущий поток и ожидает завершения текущих и поставленных в очередь операций получателя.

В результате метод операции -invokeLoadingOfFriends: ожидает завершения метода основного потока, чего не происходит, потому что вы удерживали основной поток с помощью [queue waitUntilAllOperationsAreFinished].

Попробуйте установить waitUntilDone на NO и посмотрите, поможет ли это завершить операцию.

...