dispatchMain()中主队列行为异常原因探究:任务为何跑在非主线程?
关于
dispatchMain()的用途及异常线程问题解析 原测试代码
import Foundation DispatchQueue.main.async { print("(1) on main thread: \(Thread.isMainThread)") DispatchQueue.main.async { // executed on a different thread! print("(2) on main thread: \(Thread.isMainThread)") } } dispatchMain()
输出结果
(1) on main thread: true (2) on main thread: false
按预期,主调度队列是仅在主线程执行任务的串行队列,但上述代码中第二个任务却跑到了非主线程。换成CFRunLoopRun()后两个任务都在主线程执行,下面来解释核心问题:
一、dispatchMain()的预期用途
dispatchMain()是GCD专门给纯GCD环境的程序(比如无UIKit/AppKit的命令行工具)准备的,用来启动GCD自己的主循环。它会一直运行,处理GCD队列里的任务,直到当前线程被终止或者调用dispatch_stop()。- 它的设计初衷是让GCD成为程序的核心调度器,不需要依赖系统的RunLoop(CFRunLoop/NSRunLoop)来分发任务。
二、dispatchMain()影响代码的原因
- 调用
dispatchMain()时,它会在当前线程启动GCD的主循环,但这个循环和系统主线程的RunLoop完全没关系。 - 第一个
DispatchQueue.main.async任务会在当前主线程执行,但在这个任务里再次异步提交主队列任务时,GCD的主循环没办法借助RunLoop的机制在原主线程串行处理新任务,只能新开一个线程来执行第二个任务,这就导致了第二个任务的线程检测结果为false。 - 而
CFRunLoopRun()启动的是系统原生的主线程RunLoop,DispatchQueue.main在RunLoop环境下会绑定主线程的RunLoop端口,所有主队列任务都会被放到主线程的RunLoop里串行执行,所以两个任务都能在主线程完成。
内容的提问来源于stack exchange,提问作者Valentin Milea
相关产品推荐
相关产品推荐

