Concurrency3

一、 UI和GCD的联系

有两种方式在主线程上创建任务,两种方式都是异步的,这可以保证你的app运行流畅,无论是有些任务是否被卡住:
dispatch_async 函数:Executes a block object on a dispatch queue.
dispatch_async_f 函数: Executes a C function on a dispatch queue.
注意:dispatch_sync methos cannot be called on the main queue because it will block the thread indefinitely and cause your application to deadlock. All tasks submitted to the main queue through GCD must be submitted asynchronously.(在主线程中不能使用dispatch_sync,因为使用同步的任务会使你的应用卡死。)

使用dispatch_async 函数,它需要接收两个参数:
Dispatch queue handle
The dispatch queue on which the task has to be executed.(一个分发队列,用来包含必须要执行的任务)。
Block object
The block object to be sent to the dispatch queue for asynchronous execution.(block的内容就是放到dispatch queue中的任务)。
eg:
使用dispatch_async 函数在主线程上创建任务–

- (void)mymethod
{
    dispatch_queue_t mainQueue = dispatch_get_main_queue();
    dispatch_async(mainQueue, ^{
       [[[UIAlertView alloc] initWithTitle:@"GCD"
                                  message:@"GCD is amazing"
                                 delegate:nil
                        cancelButtonTitle:@"OK"
                         otherButtonTitles:nil,nil] show];
    });
}

利用dispatch_async_f 的方式在主线程上创建任务–

typedef struct{
    char *title;
    char *message;
    char *cancelButtonTitle;
}AlertViewData;

void displayAlertView(void *paramContext){
    AlertViewData *alertData = (AlertViewData *)paramContext;
    NSString *title = [NSString stringWithUTF8String:alertData->title];

    NSString *message = [NSString stringWithUTF8String:alertData->message];

    NSString *cancelButtonTitle = [NSString stringWithUTF8String:alertData->cancelButtonTitle];

    [[[UIAlertView alloc] initWithTitle:title
                               message:message
                              delegate:nil
                     cancelButtonTitle:cancelButtonTitle
                      otherButtonTitles:nil, nil] show];

    free(alertData);
}

- (void)youmethod
{
    dispatch_queue_t mainQueue = dispatch_get_main_queue();
    AlertViewData *context = (AlertViewData *)malloc(sizeof(AlertViewData));
    if (context != NULL) {
        context->title = "GCD";
        context->message = "GCD is amazing.";
        context->cancelButtonTitle = "OK";
        dispatch_async_f(mainQueue, (void *)context, displayAlertView);
    }
}

二、执行和UI不相关的同步任务

方法:利用dispatch_sync函数

对此函数的说明:
对于所有的和UI不相关的任务,你都可以利用GCD中的全局并发队列。global concurrent queues中可以设置同步任务和异步任务。同步任务意思是并发队列会等待队列中的任务完成后才会执行队列中的下个block对象,是串行执行的;当你把一个block对象放到一个concurrent queue中,你的程序一般会立刻执行而不需要等待队列去执行这些代码。这是因为concurrent queues,正如其名,运行他的代码在非主线程上。
如果你往concurrent queue中提交了一个同步的任务,同时你又提交了另外一个同步任务到另外一个concurrent queue中,这两个同步任务会运行异步。因为这两个任务分别在不同的并发队列中。这个原理对我们来说非常重要,因为以后你可能有这样的需求“你需要完成A任务后才能运行B任务”,为了确保这个运行顺序,你需要让这个任务同步,并且需要提交到同一个队列中去。

eg:打印从1-1000,输出两遍。第二遍的打印在第一次完成后。
1.利用block object

void (^printFrom1To1000)(void) = ^{
    NSUInteger counter = 0;
    for(counter = 1; counter <= 1000;counter++){
        NSLog(@"Counter = %lu - Thread = %@",(unsigned long)counter,[NSThread currentThread]);
    }
};

-(void) mysyncMethod
{
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_sync(concurrentQueue, printFrom1To1000);
    dispatch_sync(concurrentQueue, printFrom1To1000);
}

从打印的结果可以看到,两个任务都运行在主线程上。尽管你利用了current queue来执行这两个任务,这是由于GCD优化的结果。dispatch_sync 函数会尽可能的利用当前正在执行的线程去执行你的任务。这是Apple优化的结果。
2.利用C函数来代替block object.

- (void)mysyncMethodC
{
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_sync_f(concurrentQueue, NULL, printFrom1To1000C);
    dispatch_sync_f(concurrentQueue, NULL, printFrom1To1000C);
}

void printFrom1To1000C(void *paramContext){
    NSUInteger counter = 0;
    for (counter = 1; counter <= 1000; counter++) {
        NSLog(@"Counter = %lu - Thread = %@",(unsigned long)counter,[NSThread currentThread]);
    }
}

三、执行和UI不相关的异步任务

方法:利用以下两个函数
dispatch_async : 提交的是block对象
dispatch_async_f : 提交的是C函数

eg:下面是具体用法
1)dispatch_async

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self myAsyncMethod];
}


-(void) myAsyncMethod
{
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(concurrentQueue, ^{
        __block UIImage *image = nil;
        dispatch_sync(concurrentQueue, ^{
            NSString *urlAsString = @"https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/bd_logo1_31bdc765.png";
            NSURL *url = [NSURL URLWithString:urlAsString];
            NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];

            NSError *DownloadError = nil;

            NSData *imageData = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:nil error:&DownloadError];

            if (DownloadError == nil && imageData != nil) {
                image = [UIImage imageWithData:imageData];
            }
            else if (DownloadError != nil){
               NSLog(@"Error happened = %@", DownloadError);
            }else{
               NSLog(@"No data could get downloaded from the URL.");
            }
        });

        dispatch_sync(dispatch_get_main_queue(), ^{
            /* Show the image to the user here on the main queue*/
            if (image != nil){
                /* Create the image view here */
                UIImageView *imageView = [[UIImageView alloc]
                                          initWithFrame:self.view.bounds];
                [imageView setImage:image];
                /* Set the image */
                /* Make sure the image is not scaled incorrectly */
                [imageView setContentMode:UIViewContentModeScaleAspectFit]; /* Add the image to this view controller's view */
                [self.view addSubview:imageView];
            }else{
                NSLog(@"Image isn't downloaded. Nothing to display.");
            } });


    });
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值