iOS多线程 - NSURLSession和UI更新

4

我有一个关于iOS多线程的一般性问题:

在我的简单测试应用程序中,我使用NSURLSession从服务器下载一些小图像,并在表视图中显示它们。在NSURLSession回调函数中,在检索到图像后,我像这样调用tableview.reloadData():

var session = NSURLSession.sharedSession().dataTaskWithURL(NSURL(url)) {(data, response, error) -> Void in
    /* Process images here */
    self.tableView.reloadData()
} session.resume()

图片下载几乎瞬间完成,但是表格视图更新需要10-20秒钟!要明确的是,更新委托在10-20秒内甚至没有被调用。然而,如果我将reloadData()放在主线程上,它会快速更新。像这样:
var session = NSURLSession.sharedSession().dataTaskWithURL(NSURL(url)) {(data, response, error) -> Void in
    /* Process images here */
    dispatch_async(dispatch_get_main_queue()) {
        self.tableView.reloadData()
    }
} session.resume()

所以,我的问题解决了,我可以再次安心入眠。但有人能否解释一下为什么会这样呢?我知道UI更新应该在主线程上执行,那么为什么第一种情况实际上仍然可以工作,但要花费很长时间呢?应用程序中没有其他操作,所以我甚至无法想象是什么原因导致重新加载要等待整整20秒钟。它是在等待NSURLSession完全关闭吗,还是类似于寻找大质数或挖掘比特币那样的操作?由于我对多线程的了解有限,所以对于未来的参考,任何关于这种情况的见解都将非常有帮助。

你应该阅读这篇文章(特别是“线程和并发”一节)https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/TheAppLifeCycle/TheAppLifeCycle.html - Duyen-Hoa
Apple非常明确地指出UI更新“必须”(而不仅仅是“应该”)在主线程上进行。当您确切地做出他们警告您不要做的事情时,它为什么会出现不良反应并不具有实际意义。我同意这是学术兴趣,但它完全属于观点(或推测)的范畴,因此可能不适合在这里讨论。 - Rob
1个回答

2
我们不会在除主线程之外的任何线程中更新UI,因为这会导致死锁。在这里发生的情况可能是有一个死锁持续了10-20秒钟,然后某些东西释放了死锁。
并不是说在另一个线程上更新UI总是行不通的。你所经历的只是其中的一种结果。我们无法真正知道Cocoa底层正在发生什么,所以我们也就无从得知。
只需始终在主线程上更新您的UI,以避免出现奇怪的行为。

https://chritto.wordpress.com/2012/12/20/updating-the-ui-from-another-thread/


这基本上是正确的,但我不认为你对于死锁的猜测是正确的。尝试在主线程上做其他事情(或者在试图更新UI的后台线程上)。它们都可以愉快地继续进行。 - Rob

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接