zoukankan      html  css  js  c++  java
  • 关于GCD的一些小事

    GCD确实不是什么新东西,我刚开始学iOS开发的时候,也用过皮毛。但终归不是深入学习,之前开发的时候,遇到了一个view需要同时GET三个http的数据。如果一个一个按顺序来,实在是太浪费时间,也太敷衍了事了。之前调用SkyDrive API的时候,我就发现连续几次这样调用API,等待的时间确实有点长,网速慢的话更难以接受。我其实也可以直接使用ASIHttpRequest,但是我认为,如果每次都要从开发中学会新的东西,那么就应该大胆使用自己之前不曾用过的方法。或者通过这些对比,可以找到最好的方法,到时再固定使用也不迟。

    项目需求具体为同时加载3个列表的数据,本来GCD直接使用3个异步,的确可以完成加载的任务。不过问题是,在加载的时候我禁用了UI的响应,加载完成之后,我必须重新启用UI响应。因此,3个异步进程完成后,需要再执行一些任务。显然,直接3个异步,可以通过使用一个外部变量来计数,但是这种方法有点粗暴。所以,我查阅了GCD的资料,发现有dispatch_group_t这个东西,通过先创建一个group,等这个group完成之后可以执行对应的方法。

    例子代码如下:

     1     dispatch_queue_t queue = dispatch_get_global_qeueue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
     2     dispatch_group_t group = dispatch_group_create();
     3     for(id obj in array)
     4         dispatch_group_async(group, queue, ^{
     5             [self doSomethingIntensiveWith:obj];
     6         });
     7     dispatch_group_notify(group, queue, ^{
     8         [self doSomethingWith:array];
     9     });
    10     dispatch_release(group);

    只要将dispatch_group_async调用对应的异步block,那么当所有异步block都执行完时就会执行dispatch_group_notify的block。整段代码结构清晰,也不需要那些多余的控制变量。不过值得注意是,在ARC下也要记得release那个group,因为它不是NSObject层的对象。

    上面是同时并行的例子,下面后有是一个控制信号量的例子。信号量,我之前也不知道是什么(不详细解释,具体问谷歌),其实自己也可以手动实现,不过如果用循环来作为阻塞是会浪费大量资源的。GCD提供了一种粒度更细的控制方法:

    1 dispatch_semaphore_t __block sem = dispatch_semaphore_create(1);
    2 dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
    3 
    4 //运行代码                
    5                 
    6 dispatch_semaphore_signal(sem);

    这段代码要在子线程执行,在异步时,后面的代码就会等待前面的执行完才执行。dispatch_semaphore_create(1) 是返回信号量为1的dispatch_semaphore_t,也就是同时只能有1个异步的执行。dispatch_semaphore_wait()在信号量大于0时,则执行下面的代码并将信号量-1;否则就看dispatch_time_t的timeout,如果为DISPATCH_TIME_FOREVER就会一直阻塞,DISPATCH_TIME_NOW则直接跳过。dispatch_semaphore_signal()就是将信号量+1。利用这个方法,就可以更好地控制block的异步执行。

    之前在http://www.cnblogs.com/ipinka/archive/2012/09/03/2660924.html的多选图片是通过锁来实现的,不是太优美,应该说其方法略显老旧。学习了信号量的方法,就可以写成下面这种风骚的写法:

     1 - (NSData *) imageData
     2 {
     3     NSAssert(![NSThread isMainThread], @"can't be called on the main thread due to ALAssetLibrary limitations");
     4     
     5     dispatch_semaphore_t __block sema = dispatch_semaphore_create(0);
     6     __block NSData *returnData;
     7     
     8     ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset)
     9     {
    10         ALAssetRepresentation *rep = [myasset defaultRepresentation];           //获取默认的representation
    11         CGImageRef iref = [rep fullResolutionImage];                            //获取全尺寸的CGImage
    12         UIImage *tmpImage = [UIImage imageWithCGImage:iref];                    //转换成UIImage
    13         
    14         if (iref) {
    15             if ([self.fileType isEqualToString:@"jpg"])                         //通过判断分别转为jpg或者png
    16                 returnData = UIImageJPEGRepresentation(tmpImage, 1.0);
    17             else
    18                 returnData = UIImagePNGRepresentation(tmpImage);
    19         }
    20         NSLog(@"imageData Succeed");
    21         dispatch_semaphore_signal(sema);
    22     };
    23     
    24     ALAssetsLibraryAccessFailureBlock failureblock  = ^(NSError *myerror)
    25     {
    26         NSLog(@"imageData Failed");
    27         dispatch_semaphore_signal(sema);
    28     };
    29     
    30     
    31     ALAssetsLibrary *assetslibrary = [[ALAssetsLibrary alloc] init];
    32     [assetslibrary assetForURL:self.imageReferenceURL 
    33                    resultBlock:resultblock
    34                   failureBlock:failureblock];
    35     
    36     dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
    37     
    38     return returnData;
    39 }

    感觉真的简洁明了,实际运行后效果与之前的毫无差异,以后就可以放心大胆地利用类似的方法来进行多线程的控制了。

  • 相关阅读:
    《构建之法》
    《构建之法》第一单元
    查询特殊字符
    Excel文件批量导入SQLSERVER数据库中(利用Foreach容器)
    当月的最后一天SELECT DATEADD(dd,1,DATEADD(mm, DATEDIFF(m,0,getdate())+1, 0)) 20140930 00:00:00.000
    the difference between primary key and unique key
    sql中如何再判断一个字段是否为空,如果不为空然后再Select这个字段,这要如何写呢?
    union和union all的区别
    UIImageView的基本使用
    UINavigationController导航控制器
  • 原文地址:https://www.cnblogs.com/ipinka/p/3052659.html
Copyright © 2011-2022 走看看