GCD6: 在GCD上异步执行非UI相关任务

讨论:在主队列、串行队列和并发队列上异步执行代码块才能见识到 GCD 的真正实力。

要在分派队列上执行异步任务,你必须使用下面这些函数中的其中一个:

dispatch_async为了异步执行向分派队列提交一个 Block Object(2 项都通过参数指定)

dispatch_async_f为了异步执行向分派队列提交一个 C 函数和一个上下文引用(3 项通过参数参数指定)

dispatch_async 和dispatch_sync的区别

dispatch_sync(),同步添加操作。他是等待添加进队列里面的操作完成之后再继续执行。

dispatch_queue_t concurrentQueue = dispatch_queue_create("my.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);
    NSLog(@"1");
    dispatch_sync(concurrentQueue, ^(){
        NSLog(@"2");
        [NSThread sleepForTimeInterval:10];
        NSLog(@"3");
    });
    NSLog(@"4");
输出 : 

11:36:25.313 GCDSeTest[544:303] 1
11:36:25.313 GCDSeTest[544:303] 2
11:36:30.313 GCDSeTest[544:303] 3//模拟长时间操作
11:36:30.314 GCDSeTest[544:303] 4

dispatch_async ,异步添加进任务队列,它不会做任何等待

dispatch_queue_t concurrentQueue = dispatch_queue_create("my.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);
    NSLog(@"1");
    dispatch_async(concurrentQueue, ^(){
        NSLog(@"2");
        [NSThread sleepForTimeInterval:5];
        NSLog(@"3");
    });
    NSLog(@"4");
输出:
 11:42:43.820 GCDSeTest[568:303] 1
 11:42:43.820 GCDSeTest[568:303] 4
 11:42:43.820 GCDSeTest[568:1003] 2
 11:42:48.821 GCDSeTest[568:1003] 3//模拟长时间操作时间

实例:

写一个 iOS APP, 它能从网络的 URL 上下载一个图片。下载完 成之后,APP 应该将图片展示给用户。

1、我们在并发队列上异步的启动一个 block object。

2、在这个 block 中我们使用 dispatch_sync 函数来启动另一个 Block Object,以从 URL 上下载图片。我这样做的目的是想让并发队列中剩余的代码能够等到图片下载完成之后在继续执行。从一个异步代码块上同步下载一个 URL 可以保持这个队列运行同步函数,而不是主线程。当我们从主线程角度来看的话整个运作仍是异步的。我们关心的问题是在下载图片的过程中没有阻塞主线程。

3、图片下载完毕后,为了在 UI 上将图片展示给用户,我们会在主线程上同步执行一个 Block

我们计划的框架:

dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async(concurrentQueue, ^{
__block UIImage *image = nil;
dispatch_sync(concurrentQueue, ^{
/* Download the image here */
});
dispatch_sync(dispatch_get_main_queue(), ^{
/* Show the image to the user here on the main queue*/
});
});

详细代码为:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(concurrentQueue, ^{
        __block UIImage *image = nil;
        dispatch_sync(concurrentQueue, ^{
            //开始下载图片
            NSString *urlString = @"http://a.hiphotos.baidu.com/image/pic/item/eac4b74543a9822677de5a5c8982b9014a90ebaa.jpg";
            NSURL *url = [NSURL URLWithString:urlString];
            NSURLRequest *request = [NSURLRequest requestWithURL:url];
            NSError *downloadError = nil;
            NSData *imageData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&downloadError];
            if (downloadError == nil && imageData != nil) {
                image = [UIImage imageWithData:imageData];
                //获得了图片
            }
            else if (downloadError != nil){
                NSLog(@"Error happended : %@",downloadError);
            }else{
                NSLog(@"No data could get downloaded from the URL");
            }
        });
        dispatch_sync(dispatch_get_main_queue(), ^{
            //主线程上展示图片
            if (image != nil) {
                UIImageView *imageView = [[UIImageView alloc]initWithFrame:self.view.bounds];
                [imageView setImage:image];
                [imageView setContentMode:UIViewContentModeScaleAspectFit];
                [self.view addSubview:imageView];
            }else{
                NSLog(@"Image isn‘t downloaded. Nothing to display.");
            }
        });
    });
}

下面我们来看另一个例子:

假设我们在磁盘的一个文件内存储了 1000 个随机数字的数组,我们想把这个数组加载到内存,让数字按照升序排列然后展示给用户。

如果我们没有数组,那为什么我们不先创建一个数组然后再进行加载,最后展示出来呢?


时间: 2024-10-28 20:25:31

GCD6: 在GCD上异步执行非UI相关任务的相关文章

GCD5: 用GCD同步执行非UI相关的任务

讨论: 当执行那些与 UI 无关的任务,或者与 UI 交互的任务时,和执行其他任务一样,会需要大量时间,以上情况会经常出现.例如,你想下载一个图片并想在下载完成之后展现给用户.下载过程却和 UI 没有任何关系. 对于任何与 UI 无关的任务,你可以使用 GCD 中的全局并发队列.它们允许同步和异步执行. 如果你同步提交一个任务到一个并发队列,同时提交另一个同步任务到另一个并发队列;相对而言这两个同步任务将异步运行,因为他们运行在两个不同的并发队列上.理解这一点很重要,正如我们将看到的那样,你想确

Android异步处理一:使用Thread+Handler实现非UI线程更新UI界面

Android应用的开发过程中需要把繁重的任务(IO,网络连接等)放到其他线程中异步执行,达到不阻塞UI的效果. 下面将由浅入深介绍Android进行异步处理的实现方法和系统底层的实现原理. 本文介绍Android异步处理一:使用Thread+Handler实现非UI线程更新UI界面: 即如何使用Thread+Handler的方式从非UI线程发送界面更新消息到UI线程. 概述:每个Android应用程序都运行在一个dalvik虚拟机进程中,进程开始的时候会启动一个主线程(MainThread),

Android异步处理系列文章四篇之一使用Thread+Handler实现非UI线程更新UI界面

目录: Android异步处理一:使用Thread+Handler实现非UI线程更新UI界面Android异步处理二:使用AsyncTask异步更新UI界面Android异步处理三:Handler+Looper+MessageQueue深入详解Android异步处理四:AsyncTask的实现原理 Android异步处理一:使用Thread+Handler实现非UI线程更新UI界面 概述:每个Android应用程序都运行在一个dalvik虚拟机进程中,进程开始的时候会启动一个主线程(MainTh

GCD网络多线程---同步执行,异步执行,串行队列,并行队列

总结:同步(不管是串行还是并行)----不开辟子线程 异步(不管是串行还是并行)----开辟子线程 GCD: dispatch queue 主线程的main queue 并行队列 global dispatch queue 串行队列serial queues 一般用于按顺序同步访问 #pragma mark - 加载多线程 - (void) _loadMutil { //GCD基于C语言 //1.主对列:(串行队列) dispatch_queue_t mainQueue=dispatch_get

Android异步机制一:使用Thread+Handler实现非UI线程更新UI界面

概述:每个Android应用程序都运行在一个dalvik虚拟机进程中,进程开始的时候会启动一个主线程(MainThread),主线程负责处理和ui相关的事件,因此主线程通常又叫UI线程.而由于Android采用UI单线程模型,所以只能在主线程中对UI元素进行操作.如果在非UI线程直接对UI进行了操作,则会报错: CalledFromWrongThreadException only the original thread that created a view hierarchy can tou

# 进程/线程/协程 # IO:同步/异步/阻塞/非阻塞 # greenlet gevent # 事件驱动与异步IO # Select\Poll\Epoll异步IO 以及selectors模块 # Python队列/RabbitMQ队列

1 # 进程/线程/协程 2 # IO:同步/异步/阻塞/非阻塞 3 # greenlet gevent 4 # 事件驱动与异步IO 5 # Select\Poll\Epoll异步IO 以及selectors模块 6 # Python队列/RabbitMQ队列 7 8 ############################################################################################## 9 1.什么是进程?进程和程序之间有什么

非UI线程加载图片

Processing Bitmaps Off the UI Thread 非UI线程加载图片 BitmapFactory.decode*一系列方法,在之前的高效加载大图的文章中讲到过. 如果图片的数据源是磁盘,或则网络(内存以外的其他地方),那么解析图片的方法不应该在UI线程中执行.这些数据加载任务所要花费的时间有许多不可控因素,(例如:磁盘读取速度,图片的大小,CPU的频率,等等)如果这些任务阻塞了UI线程,系统判定你的应用程序无响应,用户是有权关闭你的软件的,这样的用户体验非常不好. 这篇文

基础篇-在非UI线程中更新UI元素

个人原创,转载请注明出处: http://blog.csdn.net/supluo/article/details/ 先了解两个概念 1.UI:User Interface的缩写,用户界面的意思.你可以不恰当的理解为我们能够看到的,操作的东西:在Android中什么才称为UI呢,可以简单的理解为View及其子类等元素.这是一个不够正确的概念,只是对新手做一个简单的抛砖引玉. 2.ANR:Application Not Responding,意思是程序没有响应. 在如下情况下,Android会报出

(转)异步与非阻塞之间的区别(看到的最清晰的说明)

Asynchronous I/O, or non-blocking I/O, is a form of input/output processing that permits other processing to continue before the transmission has finished 非阻塞不一定做到异步.非阻塞只是意味着方法调用不阻塞,但是通过事件通知的方式给调用线程一个机会去完成.它的逻辑是"等可以读(写)了告诉你".这意味着工作的完成者仍然是调用者(线程)