202 votes

Attendre que deux blocs async sont exécutés avant de commencer un autre bloc

Lorsque vous utilisez GCD, nous voulons attendre jusqu'à ce que deux blocs async sont exécutées et faites avant de passer aux prochaines étapes de l’exécution. Quelle est la meilleure façon de le faire ?

Nous avons essayé ce qui suit, mais il ne semble pas fonctionner :

320voto

Jörn Eyrich Points 1256

Expédition d'utilisation de groupes: voir ici pour un exemple, "en Attente sur les Groupes de Tâches en file d'Attente" dans la Dépêche Files d'attente", chapitre de l'iOS d'Apple Développeur de la Bibliothèque de la Simultanéité Guide de Programmation

Votre exemple pourrait ressembler à quelque chose comme ceci:

dispatch_group_t group = dispatch_group_create();

dispatch_group_async(group,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {
    // block1
    NSLog(@"Block1");
    [NSThread sleepForTimeInterval:5.0];
    NSLog(@"Block1 End");
});


dispatch_group_async(group,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {
    // block2
    NSLog(@"Block2");
    [NSThread sleepForTimeInterval:8.0];
    NSLog(@"Block2 End");
});

dispatch_group_notify(group,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {
    // block3
    NSLog(@"Block3");
});

dispatch_release(group);

et pourrait produire un résultat comme ceci:

2012-08-11 16:10:18.049 Dispatch[11858:1e03] Block1
2012-08-11 16:10:18.052 Dispatch[11858:1d03] Block2
2012-08-11 16:10:23.051 Dispatch[11858:1e03] Block1 End
2012-08-11 16:10:26.053 Dispatch[11858:1d03] Block2 End
2012-08-11 16:10:26.054 Dispatch[11858:1d03] Block3

284voto

ɲeuroburɳ Points 1212

L'expansion sur Jörn Eyrich réponse (upvote sa réponse si vous upvote celui-ci), si vous n'avez pas de contrôle sur l' dispatch_async des appels pour vos blocs, comme ce pourrait être le cas pour async achèvement des blocs, vous pouvez utiliser le PGCD des groupes à l'aide de dispatch_group_enter et dispatch_group_leave directement.

Dans cet exemple, nous allons faire semblant computeInBackground est quelque chose que nous ne pouvons pas changer (imaginez que c'est un délégué de rappel, NSURLConnection completionHandler, ou quoi que ce soit), et donc nous n'avons pas accès à la répartition des appels.

// create a group
dispatch_group_t group = dispatch_group_create();

// pair a dispatch_group_enter for each dispatch_group_leave
dispatch_group_enter(group);     // pair 1 enter
[self computeInBackground:1 completion:^{
    NSLog(@"1 done");
    dispatch_group_leave(group); // pair 1 leave
}];

// again... (and again...)
dispatch_group_enter(group);     // pair 2 enter
[self computeInBackground:2 completion:^{
    NSLog(@"2 done");
    dispatch_group_leave(group); // pair 2 leave
}];

// Next, setup the code to execute after all the paired enter/leave calls.
//
// Option 1: Get a notification on a block that will be scheduled on the specified queue:
dispatch_group_notify(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
    NSLog(@"finally!");
});

// Option 2: Block an wait for the calls to complete in code already running
// (as cbartel points out, be careful with running this on the main/UI queue!):
//
// dispatch_group_wait(group, DISPATCH_TIME_FOREVER); // blocks current thread
// NSLog(@"finally!");

Dans cet exemple, computeInBackground:achèvement: est implémenté sous la forme:

- (void)computeInBackground:(int)no completion:(void (^)(void))block {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        NSLog(@"%d starting", no);
        sleep(no*2);
        block();
    });
}

De sortie (avec des horodatages à partir d'une série):

12:57:02.574  2 running
12:57:02.574  1 running
12:57:04.590  1 done
12:57:06.590  2 done
12:57:06.591  finally!

57voto

Rob Points 70987

Une autre alternative GCD est une barrière :

Il suffit de créer une file d’attente simultanée, envoyer vos deux blocs et ensuite envoyer le bloc final avec barrière, qui rendra à attendre que les deux autres à terminer.

40voto

Rob Points 70987

Je sais que vous avez demandé sur les pgcd, mais si vous vouliez, `` s’occupe aussi de ce genre de choses vraiment gracieusement, par exemple :

3voto

jkh Points 2015

La première réponse est essentiellement exact, mais si vous voulez le plus très simple pour obtenir le résultat désiré, voici un exemple de code autonome qui illustre comment le faire avec un sémaphore (qui est aussi comment envoyer des groupes de travail dans les coulisses, JFYI) :

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X