【问题标题】:Swift Threading: When to use DispatchQueue.main.async?Swift 线程:何时使用 DispatchQueue.main.async?
【发布时间】:2018-06-06 18:22:48
【问题描述】:

我相信当我调用调度队列时我明白它在做什么,但我不确定我应该在什么时候使用它,以及当我使用它时它的优点是什么。

如果我的理解是正确的,DispatchQueue.main.async { // code } 将调度包含在闭包中的代码以异步方式在主调度队列上运行。主队列具有最高优先级,通常保留用于更新 UI 以最大限度地提高应用响应能力。

我感到困惑的是:在调度队列闭包中更新 UI 元素与在闭包之外在同一位置编写代码到底有什么区别?在视图的主体中执行代码是否会更快地加载方法而不是将其发送到调度队列?如果不是,为什么?

代码示例:

class MyViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        updateUI()
    }

}

对比:

class MyViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        DispatchQueue.main.async {
            updateUI()
        }
    }
}

哪一个会更新 UI 更快?

【问题讨论】:

    标签: swift multithreading user-interface


    【解决方案1】:

    DispatchQueue.main.async 的主要用途是当您有代码在后台队列上运行并且您需要在主队列上执行特定的代码块时。

    在您的代码中,viewDidLoad 已经在主队列上运行,因此几乎没有理由使用 DispatchQueue.main.async

    但使用它不一定是错误的。但它确实改变了执行顺序。

    示例没有:

    class MyViewController: UIViewController {
        func updateUI() {
            print("update")
        }
    
        override func viewDidLoad() {
            super.viewDidLoad()
            print("before")
            updateUI()
            print("after")
        }
    }
    

    正如人们所预料的那样,输出将是:

    之前
    更新
    之后

    现在添加DispatchQueue.main.async:

    class MyViewController: UIViewController {
        func updateUI() {
            print("update")
        }
    
        override func viewDidLoad() {
            super.viewDidLoad()
            print("before")
            DispatchQueue.main.async {
                updateUI()
            }
            print("after")
        }
    }
    

    并且输出发生变化:

    之前
    之后
    更新

    这是因为异步闭包在当前运行循环完成后排队运行。

    【讨论】:

    • 我们如何知道哪些函数在主队列中运行或没有运行?
    【解决方案2】:

    我刚刚遇到了您的问题中描述的确切情况:viewDidLoad() 打电话给DispatchQueue.main.async

    在我的例子中,我想在显示视图之前修改 Storyboard 默认值。

    但是当我运行应用程序时,默认的 Storyboard 项目会暂时显示。动画转场将结束。只有这样,UI 组件才会通过viewDidLoad() 中的代码进行修改。因此,在编辑实际值之前,所有默认情节提要值都出现了令人讨厌的闪光。

    这是因为我通过一个总是首先分派到主线程的辅助函数来修改这些控件。该调度为时已晚无法在控件首次显示之前对其进行修改。

    所以:修改 viewDidLoad() 中的 Storyboard UI 而不分派到主线程。如果您已经在主线程上,请在那里完成工作。否则你最终的异步调度可能为时已晚。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-15
    • 1970-01-01
    • 2018-12-01
    • 2023-03-30
    • 2021-12-04
    • 1970-01-01
    • 2019-03-30
    相关资源
    最近更新 更多