Mam wywołanie zwrotne, które może pochodzić z dowolnego wątku. Kiedy otrzymuję to wywołanie zwrotne, chciałbym wykonać pewne zadanie w głównym wątku.
Czy muszę sprawdzać, czy jestem już w głównym wątku - czy istnieje kara za nieprzeprowadzenie tej kontroli przed wywołaniem poniższego kodu?
dispatch_async(dispatch_get_main_queue(), ^{
// do work here
});
Odpowiedzi:
Nie, nie musisz sprawdzać, czy jesteś już w głównym wątku. Wysyłając blok do kolejki głównej, planujesz tylko szeregowe wykonanie bloku w głównym wątku, co dzieje się, gdy uruchomiona zostanie odpowiednia pętla uruchamiania.
Jeśli jesteś już w głównym wątku, zachowanie jest takie samo: blok jest zaplanowany i wykonywany, gdy uruchomiona zostanie pętla uruchamiania głównego wątku.
źródło
async
powrotem do kolejki głównej, zostanie ona uruchomiona, ale może to zepsuć oczekiwany czas Twoich działań . Takie jak kod UI wviewDidLoad()
nie działa, dopóki po raz pierwszy zostanie wyświetlony widok .W przypadku asynchronicznego przypadku wysyłki opisanego powyżej nie trzeba sprawdzać, czy jesteś w głównym wątku. Jak wskazuje Bavarious, będzie to po prostu w kolejce do uruchomienia w głównym wątku.
Jeśli jednak spróbujesz wykonać powyższe czynności za pomocą a,
dispatch_sync()
a Twoje wywołanie zwrotne będzie w głównym wątku, aplikacja zablokuje się w tym momencie. Opisuję to w mojej odpowiedzi tutaj , ponieważ to zachowanie zaskoczyło mnie podczas przenoszenia kodu-performSelectorOnMainThread:
. Jak wspomniałem, stworzyłem funkcję pomocnika:który uruchomi blok synchronicznie w głównym wątku, jeśli aktualnie używana metoda nie znajduje się w głównym wątku, i po prostu wykona blok wstawiony, jeśli tak jest. Aby użyć tego, możesz użyć składni takiej jak poniżej:
źródło
dispatch_set_specific()
pomógłby w opisanym przypadku: stackoverflow.com/a/12806754/19679 .Jak wspomniano w innych odpowiedziach, dispatch_async z głównego wątku jest w porządku.
Jednak w zależności od przypadku użycia istnieje efekt uboczny, który możesz uznać za wadę: ponieważ blok jest zaplanowany w kolejce, nie zostanie on wykonany, dopóki kontrola nie wróci do pętli uruchamiania, co spowoduje opóźnienie wykonanie twojego bloku.
Na przykład,
Wydrukuje:
Z tego powodu, jeśli spodziewałeś się, że blok wykona się pomiędzy zewnętrznymi NSLogami, dispatch_async nie pomoże.
źródło
Nie, nie musisz sprawdzać, czy jesteś w głównym wątku. Oto, jak możesz to zrobić w Swift:
Jest zawarty jako standardowa funkcja w moim repozytorium, sprawdź to: https://github.com/goktugyil/EZSwiftExtensions
źródło