异步线程执行任务,结束后回到主线程比较常用的做法GCD函数

// 执行异步任务
DispatchQueue.global().async {
    
    // 回到主线程执行任务,比如刷新UI
    DispatchQueue.main.async {
        //...
    }
}

DispatchWorkItem也可以做到,而且更优雅美观,封装示例如下

// 自定义封装多线程开发
struct DXAsync {
    
    public typealias Task = () -> Void
    
    public static func async(_ task: @escaping Task) {
        _async(task)
    }
    
    public static func async(_ task: @escaping Task, mainTask: @escaping Task) {
        _async(task, mainTask: mainTask)
    }
    
    
    /// 私用方法
    /// - Parameters:
    ///   - task: 异步任务
    ///   - mainTask: 异步任务执行后,回到主线程的任务
    private static func _async(_ task: @escaping Task, mainTask: Task? = nil) {
        let workitem = DispatchWorkItem.init(block: task)
        DispatchQueue.global().async(execute: workitem)
        if let tempTask = mainTask {
            workitem.notify(queue: DispatchQueue.main, execute: tempTask)
        }
        
    }
    
    // 多线程开发-异步延迟
    @discardableResult
    public static func asyncDelay(seconds: Double,
                                    task: @escaping Task) -> DispatchWorkItem {
        
        return _asyncDelay(seconds: seconds, task: task)
    }
    
    @discardableResult
    public static func asyncDelay(seconds: Double,
                                    task: @escaping Task,
                                    mainTask: @escaping Task) -> DispatchWorkItem {
        
        return _asyncDelay(seconds: seconds, task: task, mainTask: mainTask)
    }
    
    
    
    private static func _asyncDelay(seconds: Double,
                                    task: @escaping Task,
                                    mainTask: Task? = nil) -> DispatchWorkItem {
        let workItem = DispatchWorkItem.init(block: task)
        DispatchQueue.global().asyncAfter(deadline: .now() + seconds, execute: workItem)
        if let tempTask = mainTask {
            workItem.notify(queue: DispatchQueue.main, execute: tempTask)
        }
        return workItem
    }
    
}

1.异步函数使用示例

DXAsync.async {
    print("1当前线程是",Thread.current)
}

DXAsync.async({
    print("2当前线程是",Thread.current)
}, mainTask: {
    print("3当前线程是",Thread.current)
})

// 打印
1当前线程是 <NSThread: 0x600000fa2d00>{number = 6, name = (null)}
2当前线程是 <NSThread: 0x600000f96f00>{number = 3, name = (null)}
3当前线程是 <NSThread: 0x600000fd1700>{number = 1, name = main}

2.异步延迟示例

// 全局变量
var workItem: DispatchWorkItem?
    
workItem = DXAsync.asyncDelay(seconds: 3, task: {
    print("1当前线程是",Thread.current)
}, mainTask: {
    print("2当前线程是",Thread.current)
})

//1当前线程是 <NSThread: 0x600003d84640>{number = 5, name = (null)}
//2当前线程是 <NSThread: 0x600003dd2c80>{number = 1, name = main}

为什么要有返回值?

因为是有延迟调用,所以这个异步任务可以取消,但是主线程中的任务仍然会执行

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    // 取消异步任务,但是主线程的任务还是会执行
    workItem?.cancel()
}
// 仅执行主线程的任务
//2当前线程是 <NSThread: 0x6000037f1000>{number = 1, name = main}