2013-05-04 2 views
1

Я пытаюсь завершить длинный расчет с определенным индикатором выполнения. Это нормально работает с приведенным ниже кодом. Однако в методе, который вызывает scan, он немедленно переходит на scoreWithEquation до того, как scan завершил обновление объекта StoredLibrary. Я пробовал все различные методы, ожидающие окончания очередей отправки, но все они в конечном итоге висят в пользовательском интерфейсе. Нужно ли использовать обратный вызов? Я изучил это решение, но я не понимаю, как передавать все аргументы и возвращать переменные взад и вперед.Асинхронная отправка по вызванному методу

-(void) scan{ 
if (!_sheet){ 
    [NSBundle loadNibNamed: @"ProgressSheet" owner: self]; 
} 
[NSApp beginSheet: _sheet 
    modalForWindow: [[NSApp delegate]window] 
    modalDelegate: self 
    didEndSelector: NULL 
     contextInfo: nil]; 

[_sheet makeKeyAndOrderFront:self]; 

[_progressBar setIndeterminate:YES]; 
[_progressBar setMinValue:0]; 
[_progressBar startAnimation:self]; 

__block NSMutableArray *tempTracks = [[NSMutableArray alloc]init]; 

//do stuff 

dispatch_async(dispatch_get_global_queue(0, 0), ^{ 

     //do stuff 
     [_progressBar setDoubleValue:0.f]; 
     [_progressBar setMaxValue:[listTracks count]]; 
     [_progressBar setIndeterminate:NO]; 

     for (iTunesTrack *listTrack in listTracks) { 
      //do stuff to tempTracks 
      } 
      dispatch_async(dispatch_get_main_queue(), ^{ 
       [_progressBar incrementBy:1]; 
      }); 
     } 
    } 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     [_progressBar setIndeterminate:YES]; 
     [NSApp endSheet:self.sheet]; 
     [self.sheet orderOut:self]; 
     self.listTracks = tempTracks; 
    }); 
}); 
} 

Ниже приведен код, который вызывает scan:

- (IBAction)evaluate:(id)sender { 
     if (self.storedLibrary == nil){ 
      self.storedLibrary = [[StoredLibrary alloc] init]; 
      [self.storedLibrary scan]; 
     } 
self.tableTracks = [self.storedLibrary scoreWithequation:[_scoringEquation stringValue] 
               sortOrder:[_sortOrder titleOfSelectedItem]                         
               trackLimit:[_trackLimit integerValue]]; 
} 

Я хотел бы сохранить scan и scoreWithEquation как отдельные методы, как их называют в другом месте отдельно.

ответ

3

Когда вы используете dispatch_async, отправленный блок не будет блокировать текущий поток, и выполнение будет продолжаться немедленно.

В вашем случае, когда вы вызываете сканирование, вы делаете что-то, а затем вызываете dispatch_async, чтобы делать другие вещи. все в блоке отправки не будет выполняться в этом цикле запуска, а [self.storedLibrary scan] вернется так, что оценка будет выполнена немедленно.

Если вы хотите заблокировать текущий поток (поток, на который выполняется вызов отправки), вам необходимо использовать dispatch_sync.

Если вы хотите выполнить оценку баллов после сканирования, вы можете создать serial_queue и dispatch_async как сканировать, а затем выполнить оценкуWithequation для пользовательского serial_queue. При этом выполнение не будет блокировать текущий поток, и они будут выполняться в серии.

проверка «создание последовательной очереди отправки» (http://developer.apple.com/library/ios/#documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html)

или сохранить блок завершения для выполнения scoreWithequation как обратный вызов является также возможность.

+0

Я действительно пробовал это, но он не работал. Переменная экземпляра, обновляемая 'scan' (' listTracks'), кажется, не обновляется при вызове 'scoreWithEquation'. Я думал, что, возможно, это потому, что отправка отправляется до обновления переменной экземпляра. – abroekhof

+0

в вас код scoreWithEquation вызывается до того, как выполняется «// do stuff to tempTracks» в scan. если вы отправляете в последовательную очередь, они выполняются в серии. вам нужно отправить асинхронную оценку баллов в ту же последовательность очередей «scan» – Ultrakorne

+0

Я просто попробовал еще раз и выяснил, в чем проблема. Перемещение 'self.listTracks = tempTracks;' вне блока 'dispatch_async (dispatch_get_main_queue()', казалось, было проблемой. Если оно было внутри, оно обновлялось после вызова 'scoreWithEquation'. – abroekhof

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