先看一下SDWebImage的一段程式碼
#ifndef dispatch_queue_async_safe
#define dispatch_queue_async_safe(queue, block)\
if (dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL) == dispatch_queue_get_label(queue)) {\
block();\
} else {\
dispatch_async(queue, block);\
}
#endif
#ifndef dispatch_main_async_safe
#define dispatch_main_async_safe(block) dispatch_queue_async_safe(dispatch_get_main_queue(), block)
#endif
複製程式碼
是不是很奇怪,一般來說下面的程式碼就足夠了啊,可以保證在主執行緒執行
if ([NSThread isMainThread]) {
block();
} else {
dispatch_async(dispatch_get_main_queue(), ^{
block();
})
}
複製程式碼
在github issues上看到下面的討論:
在非主佇列中呼叫MKMapView的 addOverlay方法是不安全的,即使是在主執行緒,也有可能造成崩潰。
@NachoSoto I contacted Apple DTS, they confirmed it is a bug in MapKit. But they also cautioned that the pattern of dispatch_sync
and the isMainThread
will likely run into more issues like this and the one reported by @laptobbe above.
They also explicitly stated that main queue and the main thread are not the same thing, but are have subtle differences, as shown in my demo app.
在主佇列中的任務,一定會放到主執行緒執行 所以只要是在主佇列中的任務,既可以保證在主佇列,也可以保證在主執行緒中執行。所以就可以通過判斷當前佇列是不是主佇列來代替判斷當前執行任務的執行緒是否是主執行緒,這樣會更加安全。