等待多个异步操作

Posted 小楼一夜听春雨

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了等待多个异步操作相关的知识,希望对你有一定的参考价值。

例如这样一个场景,有三个异步操作A,B,C, AB相互不依赖,但是操作C需要等AB都执行结束后才能执行

方法一 dispatch_group

 

  dispatch_group_t group = dispatch_group_create();

    

  dispatch_queue_t queue = dispatch_queue_create("a", DISPATCH_QUEUE_CONCURRENT);

 

    dispatch_group_async(group, queue, ^{

        NSLog(@"block A start");

        

        sleep(5);

        

        NSLog(@"block A end");

    });

    

    dispatch_group_async(group, queue2, ^{

        NSLog(@"block B start");

        

        sleep(10);

        

        NSLog(@"block B end");

    });

    

    dispatch_group_notify(group, queue3, ^{

        NSLog(@"block C  start");

    });

 

原理:dispatch_group可以监测多个block对象,记录当前group中有多少个block对象在执行,并在当前group中的所有block对象都执行完之后执行一个特定的block。具体方法为 dispatch_group_async方法可以将block加入到指定的dispatch_group中(可以理解为数量上+1),当block执行结束时再将其移除,而dispatch_group_notify方法会在指定的group中所有的block都执行完之后再去执行相应的block

 

方法二: dispatch_barrier_async

    dispatch_async(queue, ^{

        NSLog(@"block A start");

        

        sleep(5);

        

        NSLog(@"block A end");

 

    });

    

    dispatch_async(queue, ^{

        NSLog(@"block B start");

        

        sleep(10);

        

        NSLog(@"block B end");

        

    });

    

    dispatch_barrier_async(queue, ^{

        NSLog(@"block C start");

    });

 

原理:通过dispatch_barrier_async添加的block会在当前异步队列中在它之前添加的其他的block都执行完毕后才执行自己的block,在dispatch_barrier_async之后添加的block会等通过dispatch_barrier_async添加的block执行完毕之后才会执行

 

方法三:NSOperationQueue

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

    NSOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{

        NSLog(@"block A start");

        

        sleep(5);

        

        NSLog(@"block A end");

    }];

    

    NSOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{

        NSLog(@"block B start");

        

        sleep(10);

        

        NSLog(@"block B end");

    }];

    

    NSOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{

        NSLog(@"block C start");

    }];

    

    [operation3 addDependency:operation1];

    [operation3 addDependency:operation2];

    

    [operationQueue addOperation:operation1];

    [operationQueue addOperation:operation2];

    [operationQueue addOperation:operation3];

 

原理:NSOperationQueue支持添加dependency

 

方法四:dispatch_group_enter      dispatch_group_leave

以上三种方法适用场景为我们能够控制异步返回block的情况,当我们对异步返回的block没有控制权时,比如有回调block的方法,上述方法就失效了,此时就需要用到 dispatch_group_enter dispatch_group_leave

比如有一个方法

 - (void)handleSomethingForSeconds:(NSInteger)seconds withCompletion:(void (^)())completion

我们对completion没有直接控制权此时需要如下处理

 

    dispatch_group_t group2 = dispatch_group_create();

    

    dispatch_group_enter(group2);

    

    [self handleSomethingForSeconds:5 withCompletion:^{

        NSLog(@"complete A");

        dispatch_group_leave(group2);

    }];

    

    dispatch_group_enter(group2);

    

    [self handleSomethingForSeconds:10 withCompletion:^{

        NSLog(@"complete B");

        dispatch_group_leave(group2);

    }];

    

    dispatch_group_notify(group2, queue, ^{

        NSLog(@"block C start");

    });

 

原理:dispatch_group_enter会显示地给指定group中记录的正在执行的block数加一,dispatch_group_leave会显示地给指定group中记录的正在执行的block数减一,其他原理跟方法一相同,以此来实现等待的目的。

以上是关于等待多个异步操作的主要内容,如果未能解决你的问题,请参考以下文章

在 iOS 中等待多个网络异步调用

async-await 同时触发(等待)多个异步操作

为啥异步等待操作仍然很耗时

异步IO和协程

如何等待多个异步功能完成?

CompleableFuture