2013-05-04 49 views
1

我正在嘗試使用確定的進度條完成長時間計算。這與以下代碼正常工作。但是,在調用scan的方法中,在scan已完成更新StoredLibrary對象之前,立即轉到scoreWithEquation。我已經嘗試了所有不同的方法來等待調度隊列完成,但他們最終都掛起了用戶界面。我需要使用回撥嗎?我已經研究過這個解決方案,但我不明白如何傳遞所有參數並來回返回變量。被調用方法中的異步調度

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

我想保持scanscoreWithEquation作爲單獨的方法,因爲他們在別處單獨調用。

回答

3

當您使用dispatch_async時,分派的塊將不會阻塞當前線程,並立即繼續執行。

在你的情況下,當你調用scan時,你會做一些事情,然後調用dispatch_async去做其他的事情。調度塊中的所有內容都不會在此運行循環中執行,並且[self.storedLibrary掃描]返回,所以score將立即執行。

如果要阻止當前線程(執行調度調用的線程),則需要使用dispatch_sync。

如果您想要在掃描後執行scoreWithequation,則可以創建serial_queue和dispatch_async,然後對自定義的serial_queue進行掃描,然後對它進行score評分。這樣做執行不會阻塞當前線程,並且它們將在系列中執行。

檢查「創建串行調度隊列」(http://developer.apple.com/library/ios/#documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html

或保持完成塊執行scoreWithequation作爲回調也是一種可能性。

+0

我實際上已經嘗試過這種方式,但它不起作用。 'scan'正在更新的實例變量('listTracks')在調用'scoreWithEquation'時似乎沒有更新。我在想這也許是因爲在更新實例變量之前發送了調度。在你執行掃描的代碼scoreWithEquation之前調用「//執行到tempTracks的東西」時會調用 – abroekhof 2013-05-04 22:15:13

+0

。如果您調度到一個串行隊列,它們將在系列中執行。你必須調度異步scoreWithequation到「掃描」相同的串行隊列 – Ultrakorne 2013-05-04 22:24:11

+0

我只是試了一遍,找出了什麼問題。移動'self.listTracks = tempTracks;''dispatch_async(dispatch_get_main_queue()')塊外部似乎是個問題,如果它在裏面,它會在'scoreWithEquation'被調用後更新。 – abroekhof 2013-05-04 22:42:45