等待多个异步操作

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

方法一: 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数减一,其他原理跟方法一相同,以此来实现等待的目的。

时间: 2024-10-19 07:22:49

等待多个异步操作的相关文章

程序员要拥抱变化,聊聊Android即将支持的Java 8

原文链接:http://wetest.qq.com/lab/view/308.html 商业转载请联系腾讯WeTest获得授权,非商业转载请注明出处. WeTest 导读 Java 9预计今年也会正式发布,Java 8这个最具变革性且变革性最适于GUI程序的版本,Android终于准备正式支持.从自己开发JavaFx的感受,说一说Java 8应该使用的新特性.程序员,你应该拥抱变化. (注:本文不讲具体语法,具体语法请下载下方分享的<Java 8实战>.) James Lau(google的产

HttpApplication中的异步线程

一.Asp.net中的线程池设置 在Asp.net的服务处理中,每当服务器收到一个请求,HttpRuntime将从HttpApplication池中获取一个HttpApplication对象处理此请求,请求的处理过程将被排入线程池中,对于Asp.net来说,在Machine.config文件的processModel部分中可以设置线程池中的参数. Asp.net线程相关的参数配置: 参数 配置 autoConfig 基于服务器的配置自动设置. maxWorkerThreads 设置每个CPU的最

Boost.Asio技术文档

Christopher Kohlhoff Copyright ? 2003-2012 Christopher M. Kohlhoff 以Boost1.0的软件授权进行发布(见附带的LICENSE_1_0.txt文件或从http://www.boost.org/LICENSE_1_0.txt) Boost.Asio是用于网络和低层IO编程的跨平台C++库,为开发者提供了C++环境下稳定的异步模型. 综述 基本原理 应用程序与外界交互的方式有很多,可通过文件,网络,串口或控制台.例如在网络通信中,完

[.NET] 利用 async &amp; await 进行异步 IO 操作(整理中...)

利用 async & await 进行异步 IO 操作 可以使用异步函数访问文件.使用异步功能,可以调用异步方法,而不使用回调或拆分您在多个方法或 lambda 表达式中的代码. 若要使同步代码异步,则调用异步方法而不是一个同步方法并添加几个关键字到代码中. 您可能认为添加的以下原因 asynchrony 到文件访问调用: Asynchrony 建议于应用程序的响应能力更强.,因为是一个操作的 UI 线程可以执行其他工作. 如果 UI 线程必须执行需要很长时间的代码(例如,超过 50 毫秒),U

Boost.Asio入门(CSDN也有Markdown了,好开森)

Boost.Asio入门 首先,让我们先来了解一下什么是 Boost.Asio?怎么编译它?了解的过程中我们会给出一些例子.然后在发现 Boost.Asio 不仅仅是一个网络库的同时你也会接触到 Boost.Asio 中最核心的类--io_service. 什么是Boost.Asio 简单来说,Boost.Asio是一个跨平台的.主要用于网络和其他一些底层输入/输出编程的 C++ 库. 网络 API 的设计方式有很多种,但是 Boost.Asio 的的方式远远优于其它的设计方式.它在 2005

javascript的异步编程解决方案收集

缘起 没理解js异步的同学看下面的例子: for (var i = 0; i < 5; i++) { //模拟一个异步操作 setTimeout(() => { console.log(i); }, 1000); } 我们想要的结果是:0,1,2,3,4 结果却出乎意料:5,5,5,5,5 分析 js的特点就是单线程异步非堵塞.需要好好理解这句话:js对于异步操作,不会停下来等待上一个异步操作完成,才进行下一个异步操作. 如果要达到顺序执行,只能用回调:也就是上一个异步操作完成时,再调用下一个

JDK AIO编程

NIO2.0引入了新的异步通道的概念,并提供了异步文件通道和异步套接字通道的实现.异步通道提供两种方式获取获取操作结果. 通过java.util.concurrent.Future类来表示异步操作的结果: 在执行异步操作的时候传入一个java.nio.channels. CompletionHandler接口的实现类作为操作完成的回调. NIO2.0的异步套接字通道是真正的异步非阻塞I/O,它对应UNIX网络编程中的事件驱动I/O(AIO),它不需要通过多路复用器(Selector)对注册的通道

Boost.Asio c++ 网络编程翻译(6)

io_service类 你应该已经发现大部分使用Boost.Asio编写的代码都会使用几个ios_service的实例.ios_service是这个库里面最重要的类:它负责和操作系统打交道,等待所有异步操作的结束,然后为每一个异步操作调用完成处理程序. 如果你选择用同步的方式来创建你的应用,你不需要考虑我将在这一节向你展示的东西. 你可以用几种不同的方式来使用io_service.在下面的例子中,我们有3个异步操作,2个socket连接和一个计时器等待: 有一个io_service和一个处理线程

[js高手之路] es6系列教程 - promise常见用法详解(resolve,reject,catch,then,all,race)

关于promise我在之前的文章已经应用过好几次,如[js高手之路]Node.js+jade+express+mongodb+mongoose+promise实现todolist,本文就来讲解下promise的常见用法. 为什么会有promise,他的作用是什么? promise主要是为了解决js中多个异步回调难以维护和控制的问题. 什么是promise? 从图中,我们可以看出,Promise是一个函数,这个函数上有在项目中常用的静态方法:all, race, reject,resolve等,原