dispatch_async(dispatch_get_main_queue(),^{})存在的一个坑

dispatch_async(dispatch_get_main_queue(),^{})存在的一个坑

0.1642017.06.27 10:19:33字数 228阅读 3444

-(BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions{// Override point for customization after application launch.NSLog(@"before main queue : %@",[NSThread currentThread]);dispatch_async(dispatch_get_main_queue(),^{NSLog(@"main queue");});NSLog(@"after main queue : %@",[NSThread currentThread]);returnYES;}2017-06-2709:33:57.001TestMain[1811:19444]before main queue:{number=1,name=main}2017-06-2709:33:57.001TestMain[1811:19444]after main queue:{number=1,name=main}2017-06-2709:33:57.012TestMain[1811:19444]main queue

可以看到在main thread中,执行顺序并不是和代码顺序一样,

dispatch_async(dispatch_get_main_queue(),^{NSLog(@"main queue");});

最后执行。

如果不注意的话,可能会导致一些问题。

-(BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions{// Override point for customization after application launch.NSLog(@"before main queue : %@",[NSThread currentThread]);dispatch_async(dispatch_get_main_queue(),^{NSLog(@"main queue");self.label=[UILabel new];});NSLog(@"after main queue : %@",[NSThread currentThread]);NSLog(@"self.label: %@",self.label);returnYES;}before main queue:{number=1,name=main}after main queue:{number=1,name=main}self.label:(null)main queue

解决方法

参考SDWebImage的宏定义,判断一下当前是不是主线程,如果是直接执行,如果不是,异步执行

#ifndef dispatch_main_async_safe    #define dispatch_main_async_safe(block)\    if (strcmp(dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL), dispatch_queue_get_label(dispatch_get_main_queue())) == 0) {\    block();\    } else {\    dispatch_async(dispatch_get_main_queue(), block);\    }    #endif

将需要顺序的执行的代码放到同一个作用域里面

原因

应该是和runloop有关的,但是具体的解释还没想明白。

dispatch_async(dispatch_get_main_queue(),^{NSLog(@"main queue");self.label=[UILabel new];});

dispatch_async将block提交给了queue然后立即返回,但是block什么时候执行,由queue说了算。然后,就不知道了……

更新

block 什么时候执行由Runloop说了算,不是由queue说了算,实际就是下一个runloop循环会执行,因为runloop在唤醒后会去处理相关的任务

调用信息

void_dispatch_main_queue_callback_4CF(void*ignored DISPATCH_UNUSED){// the main queue cannot be suspended and no-one looks at this bit// so abuse it to avoid dirtying more memoryif(_dispatch_main_q.dq_side_suspend_cnt){return;}_dispatch_main_q.dq_side_suspend_cnt=true;_dispatch_main_queue_drain(&_dispatch_main_q);_dispatch_main_q.dq_side_suspend_cnt=false;}

你可能感兴趣的:(dispatch_async(dispatch_get_main_queue(),^{})存在的一个坑)