10

I need to send multiple tasks to Grand Central Dispatch to run. Some tasks will finish first, while some will finish last.

How do I know all my tasks in Grand Central Dispatch finished?

Should I use a counter to record the number of tasks finished? Any smarter method?

Kara
  • 6,115
  • 16
  • 50
  • 57
user403015
  • 7,209
  • 19
  • 66
  • 100

3 Answers3

23

You can use dispatch groups to be notified when all tasks completed. This is an example from http://cocoasamurai.blogspot.com/2009/09/guide-to-blocks-grand-central-dispatch.html

dispatch_queue_t queue = dispatch_get_global_queue(0,0);
dispatch_group_t group = dispatch_group_create();

dispatch_group_async(group,queue,^{
    NSLog(@"Block 1");
});

dispatch_group_async(group,queue,^{
    NSLog(@"Block 2");
});

dispatch_group_notify(group,queue,^{
    NSLog(@"Final block is executed last after 1 and 2");
});
Martin Ullrich
  • 94,744
  • 25
  • 252
  • 217
  • Thanks. Does iOS support this feature? – user403015 Mar 09 '12 at 10:39
  • Dev-Guide sais "Available in iOS 4.0 and later." (https://developer.apple.com/library/ios/#documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html#//apple_ref/doc/uid/TP40008079) – Martin Ullrich Mar 09 '12 at 10:40
3

If you want to control one task to execute at the end,you can use dispatch_group_t,If you want one task not only to execute after some tasks but also to execute before some tasks,you can use dispatch_barrier_sync:

dispatch_queue_t queue = dispatch_queue_create("com.example.gcd", DISPATCH_QUEUE_CONCURRENT);

dispatch_async(queue, ^{ printf("1");});

dispatch_async(queue, ^{ printf("2");});

dispatch_barrier_sync(queue, ^{ printf("3");});

dispatch_async(queue, ^{ printf("4");});

dispatch_async(queue, ^{ printf("5");});

it may print

 12345 or 21354 or ... but 3 always after 1 and 2, and 3 always before 4 and 5

If your want to control the order exactly, you can use dispatch_sync or Serial Dispatch Queue,or NSOperationQueue.If you use NSOperationQueue,use the method of "addDependency" to control the order of tasks:

NSOperationQueue *queue = [[NSOperationQueue alloc] init];

NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"op 1");
}];

NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"op 2");
}];

NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"op 3");
}];

//op3 is executed last after op2,op2 after op1    
[op2 addDependency:op1];
[op3 addDependency:op2];

[queue addOperation:op1];
[queue addOperation:op2];
[[NSOperationQueue mainQueue] addOperation:op3];

It will always print:

op1 op2 op3
ChenYilong
  • 8,543
  • 9
  • 56
  • 84
2

You can achieve this using GCD using DispatchGroup in swift 3. You can get notified when all tasks are finished.

 let group = DispatchGroup()

    group.enter()
    run(after: 6) {
      print(" 6 seconds")
      group.leave()
    }

    group.enter()
    run(after: 4) {
      print(" 4 seconds")
      group.leave()
    }

    group.enter()
    run(after: 2) {
      print(" 2 seconds")
      group.leave()
    }

    group.enter()
    run(after: 1) {
      print(" 1 second")
      group.leave()
    }


    group.notify(queue: DispatchQueue.global(qos: .background)) {
      print("All async calls completed")
}
Abhijith
  • 3,094
  • 1
  • 33
  • 36