SDWebImage源码之宏定义dispatch_main_async_safe分析详解

今天在阅读 SDWebImage 的源码,发现了这段有趣的代码。

SDWebImage源码之宏定义dispatch_main_async_safe分析详解_第1张图片
心之所向

SDWebImage这个库里的一段宏定义代码:


SDWebImage源码之宏定义dispatch_main_async_safe分析详解_第2张图片

先对这段代码做一个简单的解读。显然 #ifndef 是为了提高代码的严谨,防止重复定义 dispatch_main_async_safe。

关于判断条件的改变的原因则是复杂得多了,具体可以阅读 GCD's Main Queue vs. Main Thread

官方文档这样写到:

Calling an API from a non-main queue that is executing on the main thread will lead to issues if the library (like VektorKit) relies on checking for execution on the main queue.

意思大概是如果在主线程执行非主队列调度的API,而这个API需要检查是否由主队列上调度,那么将会出现问题。

SDWebImage 就是从判断是否在主线程执行改为判断是否由主队列上调度。而由于主队列是一个串行队列,无论任务是异步同步都不会开辟新线程,所以当前队列是主队列等价于当前在主线程上执行。可以这样说,在主队列调度的任务肯定在主线程执行,而在主线程执行的任务不一定是由主队列调度的。

下面通过自己写的demo来帮助理解


SDWebImage源码之宏定义dispatch_main_async_safe分析详解_第3张图片
demo

当在子线程中调用setImageUrl方法时会发现先走block外面也就是先输出2222.

当在主线程中调用时会先走block里面。

当你需要dispatch_async(dispatch_get_main_queue(), blockSD);获取主线程的时候 也就是执行非主队列调度API,而这个API需要检查是否由主队列上调度,那么将会出现问题。所以需要先判断当前是否在主线程。

学习能让你快乐 快乐你就拍拍手。

你可能感兴趣的:(SDWebImage源码之宏定义dispatch_main_async_safe分析详解)