GCD 主线程崩溃问题(需要解释)?

Posted

技术标签:

【中文标题】GCD 主线程崩溃问题(需要解释)?【英文标题】:GCD Main Thread Crash Issue (Explanation Needed)? 【发布时间】:2018-02-06 08:39:45 【问题描述】:

为什么这段代码会导致崩溃?

 DispatchQueue.main.sync 
        // Operation To Perform 
 

为什么我们必须这样写:-

DispatchQueue.global().async(execute: 
    print("test")
    DispatchQueue.main.sync
        print("main thread")
    
)

当我们在 CellForRowAt 或任何其他线程中编写代码时,它会在主线程或全局线程中以同步或异步方式工作?

【问题讨论】:

What does main.sync in global().async mean?的可能重复 为什么会崩溃 简而言之调用同步并定位当前队列是一个死锁(调用队列等待同步块完成,但它没有启动,因为目标队列(相同)正忙于等待完成的同步调用),这可能就是崩溃的原因。 对于第二个块:您正在创建全局队列,然后您正在获取主队列,所以现在没有死锁 ***.com/a/46732195/2912282 main.async vs main.sync() vs global().async in Swift3 GCD的可能重复 【参考方案1】:

根据 Apple,尝试在主队列上同步执行工作项会导致死锁

所以写DispatchQueue.main.sync 会导致死锁情况,因为应用程序执行的所有UI操作都在主队列上执行,除非我们手动切换后台队列上的某些任务。这也回答了您关于调用哪个线程 CellForRowAt 的问题。所有与UI操作或UIkit相关的方法都是从主线程调用的

同步执行任务意味着阻塞线程直到任务未完成,在这种情况下,您试图阻塞系统/应用程序已经执行某些任务的主线程,这可能导致死锁。完全不建议阻塞主线程,这就是为什么我们需要异步切换到后台线程,这样主线程就不会被阻塞。

要了解更多信息,您可以访问以下链接: https://developer.apple.com/documentation/dispatch

【讨论】:

【参考方案2】:

为什么总要崩溃

DispatchQueue.main.sync 
    // Operation To Perform 

调用同步并定位当前队列是一个死锁(调用队列等待同步块完成,但它没有启动,因为目标队列(相同)正忙于等待同步调用完成),这可能是崩溃的原因.

对于第二个块:您正在创建全局队列,然后您正在获取主队列,所以现在没有死锁

如果您曾经使用过semaphore,如果您不小心也会遇到同样的问题 它有两个方法waitsignalwait 如果你阻止main thread 那么你的代码将永远不会执行。

希望对你有帮助

【讨论】:

【参考方案3】:
 DispatchQueue.main.sync 
     // Operation To Perform 
 

在您已经使用的串行队列(如main)上调用同步将导致死锁。第一个进程无法完成,因为它正在等待第二个进程完成,而第二个进程无法完成,因为它正在等待第一个进程完成等等。

DispatchQueue.global().async(execute: 
    print("test")
    DispatchQueue.main.sync
        print("main thread")
    
)

当您将任务移动到global() 队列时,从这里调用主线程上的sync 起作用。

在 raywenderlich.com 上有一个很棒的 2 部分 GCD 教程,我鼓励您阅读 https://www.raywenderlich.com/148513/grand-central-dispatch-tutorial-swift-3-part-1。

【讨论】:

以上是关于GCD 主线程崩溃问题(需要解释)?的主要内容,如果未能解决你的问题,请参考以下文章

GCD - 如何在主线程上等待在主队列上执行的异步回调

iOS开发多线程篇 07 —GCD的基本使用

GCD 全局队列任务在主线程上运行

UIImageView 图像未在 GCD 的主线程上更新

多线程简介及GCD的使用

在 Swift 中,如何在 GCD 主线程上调用带参数的方法?