Dla drugiej części pytania dotyczącej nutą sprawie zamrożenia:
Dzwoniąc dispatch_sync
w kolejce, zawsze upewnić się, że ta kolejka nie jest już aktualna kolejka (dispatch_get_current_queue()
). Ponieważ spowoduje umieszczenie twojego bloku w kolejce w kolejce przekazanej jako pierwszy parametr, a następnie będzie oczekiwał na wykonanie tego bloku przed kontynuowaniem.
Jeśli więc dispatch_get_current_queue()
i kolejka, w której umieściliśmy blok, są takie same, a mianowicie główna kolejka w twoim przypadku, główna kolejka zablokuje wywołanie funkcji dispatch_sync do ... głównej kolejki w trakcie wykonywania bloku, ale nie może, ponieważ kolejka jest zablokowana, i masz piękny zakleszczenie tutaj.
Jednym z rozwiązań ([EDIT] aż iOS6):
dispatch_queue_t main = dispatch_get_main_queue();
dispatch_block_t block =^
{
[[NSNotificationCenter defaultCenter] postNotificationName:kNotificationAuthenticationSuccess object:nil userInfo:ret];
};
if (dispatch_get_current_queue() == main)
block(); // execute the block directly, as main is already the current active queue
else
dispatch_sync(main, block); // ask the main queue, which is not the current queue, to execute the block, and wait for it to be executed before continuing
[EDIT] Bądź ostrożny, dispatch_get_current_queue()
jest używane tylko do celów debugowania i nigdy w produkcji. W rzeczywistości dispatch_get_current_queue
jest przestarzałe od iOS6.1.3.
Jeśli jesteś w szczególnym przypadku głównej kolejki (która jest związana tylko z głównym wątkiem), możesz zamiast tego przetestować [NSThread isMainThread]
zgodnie z sugestią @ meaning-matters.
Nawiasem mówiąc, to na pewno trzeba dispatch_sync
w Twoim przypadku? Przypuszczam, że wysłanie powiadomienia nieco później, unikanie blokowania, dopóki nie zostanie wysłane, jest dopuszczalne w twoim przypadku, więc możesz również rozważyć użycie dispatch_async
(zamiast używać dispatch_sync
i wymagającego warunku porównywania kolejki), co pozwoli uniknąć impasu problem też.
To deadlocking bo jesteś enqueuing blok na głównej kolejki - co jest w głównym wątku - i mówi główny wątek czekać na które blok do ukończenia. –
Ponieważ odpowiedź, którą zaakceptowałeś, wcale nie rozwiązuje problemu, o który pytałeś, usunąłem tę część z pytania. Pytanie o zakleszczenie zostało już wielokrotnie potwierdzone (i jest również w dokumentach): http://stackoverflow.com/questions/7816159/dispatch-sync-on-main-queue-hangs-in-unit-test, http : //stackoverflow.com/questions/10315645/app-blocks-while-dipatching-a-queue, http://stackoverflow.com/questions/10984732/gcd-why-cant-we-use-a-dispatch-sync -do-bieżącej-kolejki, ale myślałem, że pytanie o odgadnięcie funkcji GCD było całkiem interesujące. –
Dzięki.Gdybym wiedział, że to był problem z zakleszczeniem, mógłbym odpowiednio dostosować pytanie lub znaleźć rozwiązanie, wyszukując google. Byłoby miło wiedzieć, jak wywołać dispatch_sync, ale może nie jest to właściwe rozwiązanie. – teubanks