2012-06-27 4 views
1

У меня есть метод myButtonAction, который выполняет некоторые тяжелые вычисления, которые мне нужно запускать в фоновом потоке, в то время как я загружаю представление, указывающее «Выполнение задачи» в основном потоке. Как только фоновый поток завершит выполнение метода, мне нужно удалить представление «прогресс задачи» и загрузить другое представление в основной поток.Как обеспечить синхронизацию потоков

[self performSelectorInBackground:@selector(myButtonAction) withObject:nil]; 
[self performSelectorOnMainThread:@selector(LoadView) withObject:nil waitUntilDone:YES]; 

Проблема я столкнулся в том, что, перед тем myButtonAction завершает выполнение, то LoadView завершает свое выполнение. Как я могу убедиться, что LoadView запускает выполнение только после завершения myButtonAction.

Примечание: myButtonAction имеет определение метода в другом классе.

ответ

2

Использование Grand Central Dispatch:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
    [self myButtonAction]; 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     [self LoadView]; 
    }); 
}); 

Или, если вы хотите остаться с performSelector методами:

[self performSelectorInBackground:@selector(loadViewAfterMyButtonAction) withObject:nil]; 

где

- (void)loadViewAfterMyButtonAction 
{ 
    [self myButtonAction]; 
    [self performSelectorOnMainThread:@selector(LoadView) withObject:nil waitUntilDone:YES]; 
} 
1

Вам нужно сделать следующее -

[self performSelectorInBackground:@selector(myButtonAction) withObject:nil]; 

- (void)myButtonAction { 
    //Perform all the background task 

    //Now switch to main thread with all the updated data 
    [self performSelectorOnMainThread:@selector(LoadView) withObject:nil waitUntilDone:YES]; 
} 

EDIT - Тогда вы можете попробовать -

[self performSelectorInBackground:@selector(buttonActionInBackground) withObject:nil]; 

- (void)buttonActionInBackground { 
     [self myButtonAction]; 

     //Now switch to main thread with all the updated data 
    [self performSelectorOnMainThread:@selector(LoadView) withObject:nil waitUntilDone:YES]; 
    } 

Теперь вам не нужно менять myButtonAction.

+0

'myButtonAction' находится в другом классе, который я не должен редактировать. –

+0

@XaviValero - проверить отредактированный пост, а также, если хотите, вы можете пойти на GCD. – rishi

0

я понимаю, что этот код вызывается в конце myButtonAction:

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

Теперь не удивительно, что LoadView завершается до завершения myButtonAction, потому что вы сказали, что ждать, пока это не будет сделано с «waitUntilDone: ДА» , Назовите его в конце с waitUntilDone: NO.

Для простых решений такого рода проблем взгляните на то, чтобы вводить вызовы селектора в цикл основного запуска с использованием [self performSelector:@selector(sel) withObject:obj afterDelay:0.0] или NSTimer - например, если вы хотите дождаться завершения обновлений пользовательского интерфейса.

0

Я использую Semaphore Design Pattern для этих целей.

+0

Это то, что я называю полностью за бортом. GCD, как было предложено в первом ответе, решает проблему очень легко, в основном без усилий для программиста и очень мало шансов получить это неправильно. – gnasher729