iPhone-Grand Central Dispatch main thread

Używam z powodzeniem, grand central dispatch w moich aplikacjach, ale zastanawiałem się, jaka jest prawdziwa zaleta używania czegoś takiego:

dispatch_async(dispatch_get_main_queue(), ^{ ... do stuff

Lub nawet

dispatch_sync(dispatch_get_main_queue(), ^{ ... do stuff

Chodzi mi o to, że w obu przypadkach uruchamiasz blok do wykonania na głównym wątku, dokładnie tam, gdzie działa aplikacja, a to nie pomoże zmniejszyć obciążenia. W pierwszym przypadku nie masz żadnej kontroli, kiedy blok będzie działał. Widziałem przypadki blokowania w pół sekundy po tym, jak je zwolniłeś. Na drugi przypadek jest podobny do

[self doStuff];
Prawda? Ciekawe, co myślicie.
Author: Honey, 2011-10-26

6 answers

Wysyłanie bloku do kolejki głównej zwykle odbywa się z kolejki w tle, aby zasygnalizować, że pewne przetwarzanie w tle zostało zakończone, np.

- (void)doCalculation
{
    //you can use any string instead "com.mycompany.myqueue"
    dispatch_queue_t backgroundQueue = dispatch_queue_create("com.mycompany.myqueue", 0);

    dispatch_async(backgroundQueue, ^{
        int result = <some really long calculation that takes seconds to complete>;

        dispatch_async(dispatch_get_main_queue(), ^{
            [self updateMyUIWithResult:result];
        });    
    });
}

W tym przypadku wykonujemy długie obliczenia w kolejce w tle i musimy zaktualizować nasz interfejs po zakończeniu obliczeń. Aktualizacja interfejsu zwykle musi być wykonywana z kolejki głównej, więc "zasygnalizujemy" z powrotem do kolejki głównej używając drugiego zagnieżdżonego dispatch_async.

Są prawdopodobnie inne przykłady, w których możesz chcieć wysyłanie z powrotem do kolejki głównej, ale zazwyczaj odbywa się to w ten sposób, np. zagnieżdżanie z bloku wysyłanego do kolejki w tle.

  • przetwarzanie w tle zakończone - > update UI
  • fragment danych przetwarzanych w kolejce w tle - > sygnałowa Kolejka główna, aby rozpocząć następny fragment
  • przychodzące dane sieciowe w kolejce w tle - > główna Kolejka sygnału, w której dotarła wiadomość
  • etc etc

Dlaczego warto wysłać do kolejki głównej z główna Kolejka... Cóż, generalnie nie zrobiłbyś tego, chociaż prawdopodobnie mógłbyś to zrobić, aby zaplanować jakąś pracę do zrobienia następnym razem wokół pętli run.

 291
Author: Robin Summerhill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-21 12:39:40

Wysyłanie bloków do kolejki głównej z głównego wątku może być użyteczne. Daje to kolejce głównej możliwość obsługi innych bloków, które zostały ustawione w kolejce, dzięki czemu nie blokuje się po prostu wykonywania wszystkich innych.

Na przykład można napisać zasadniczo pojedynczy serwer gwintowany, który mimo to obsługuje wiele jednoczesnych połączeń. Tak długo, jak żaden pojedynczy blok w kolejce nie trwa zbyt długo, serwer pozostaje reagujący na nowe żądania.

Jeśli twój program nic nie robi, ale spędza całe życie reagując na wydarzenia, To może być całkiem naturalne. Wystarczy skonfigurować procedury obsługi zdarzeń tak, aby działały w kolejce głównej, a następnie wywołać metodę dispatch_main ().

 15
Author: bames53,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-28 21:31:15

Mam nadzieję, że dobrze rozumiem twoje pytanie, ponieważ zastanawiasz się nad różnicami między dispatch_async i dispatch_sync?

dispatch_async

Wysyła blok do kolejki asynchronicznie. Oznacza to, że wyśle blok do kolejki i nie będzie czekać na jego powrót przed kontynuowaniem wykonywania pozostałego kodu w Twojej metodzie.

dispatch_sync

Wyśle blok do kolejki synchronicznie. Uniemożliwi to dalsze wykonywanie pozostałego kodu w metoda dopóki blok nie zakończy wykonywania.

Używałem głównie dispatch_async do kolejki w tle, aby uzyskać pracę z kolejki głównej i skorzystać z dodatkowych rdzeni, które urządzenie może mieć. Następnie dispatch_async do głównego wątku, jeśli muszę zaktualizować interfejs.

Powodzenia

 11
Author: timthetoolman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-18 15:20:06

Jedno miejsce, gdzie jest to przydatne, to czynności interfejsu użytkownika, takie jak ustawienie spinnera przed długą operacją:

- (void) handleDoSomethingButton{

    [mySpinner startAnimating];

    (do something lengthy)
    [mySpinner stopAnimating];
}

Nie zadziała, ponieważ blokujesz główny wątek podczas swojej długiej sprawy i nie pozwalasz Uikitowi uruchomić spinnera.

- (void) handleDoSomethingButton{
     [mySpinner startAnimating];

     dispatch_async (dispatch_get_main_queue(), ^{
          (do something lengthy)
          [mySpinner stopAnimating];
    });
}

Zwróci kontrolę do pętli run, która zaplanuje aktualizację interfejsu użytkownika, uruchomi spinner, a następnie otrzyma następną rzecz z kolejki dispatch, która jest Twoim rzeczywistym przetwarzaniem. Po zakończeniu przetwarzania, animacja zostanie wywołana, a Ty powrócisz do pętli run, gdzie interfejs zostanie zaktualizowany o stop.

 7
Author: weaselfloss1,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-13 23:53:13

Swift 3 & 4

Uruchamianie kodu w głównym wątku

DispatchQueue.main.async {
    // Your code here
}
 3
Author: Niall Kiddle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-16 12:23:56

Asynchroniczny oznacza asynchroniczny i powinieneś go używać przez większość czasu. Nigdy nie należy wywoływać synchronizacji w głównym wątku, ponieważ spowoduje to zablokowanie interfejsu użytkownika do czasu zakończenia zadania. Tutaj jest lepszy sposób, aby to zrobić w Swift:

runThisInMainThread { () -> Void in
    // Run your code like this:
    self.doStuff()
}

func runThisInMainThread(block: dispatch_block_t) {
    dispatch_async(dispatch_get_main_queue(), block)
}

Its included as a standard function in my repo, check it out: https://github.com/goktugyil/EZSwiftExtensions

 1
Author: Esqarrouth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-06 03:44:53