iOS知识小集之main-queue!=main-thread
GCD main queue
和main thread
的关系
dispatch_get_main_queue()
返回main queue
,该队列会被绑定到main thread
,所以我们如果我们将block
提交到main queue
,那么该block
将会在主线程中执行。
dispatch_sync(queue, block)
向 main queue
提交block
1 | /// Current thread is main thread |
大家有没有注意到,Log
输出表明执行Block
时的线程为主线程,根据我们以往的经验,dispatch_get_global_queue
获取到的队列,队列中的Block
应该是在Secondly thread
中执行,为什么这里会是在主线程中呢。
答案就是在dispatch_sync
语句,libdispatch
在commit中进行了优化,只要目标queue
不是main queue
,那么提交的Block
就会直接在原线程中执行,这就能解释为什么上面的demo
程序中输出的Log
显示是主线程。
那么,这种会不会有潜在的问题呢?
isMainThread
带来的潜在问题
首先,我们看一个Radar,大概意思是,即使MapKit
框架的addOverlay
方法在主线程执行,但是由于其不是在main queue
中执行的,会导致Crash
,这是因为MapKit
内部在main queue
中使用dispatch_queue_set_specific
设置了数据,当你在其它队列中执行时,会由于没有该数据从而导致Crash
。
避免使用isMainThread
所以,我们需要避免使用isMainThread
,而是判断是不是main queue
,我们可以使用两种方法来判断:
- 使用
dispatch_queue_set_specific
在main queue
上设置flag
,然后做判断,有该flag
即为main queue
. - 判断
dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL) == dispatch_queue_get_label(dispatch_get_main_queue())
,main queue
设置了label
,可以通过其来判断。
总结
main queue
中的Block
一定在主线程中执行。- 主线程可以对应多个
queue
,既可以有任意的队列,其Block
可以在主线程中执行。