ios - 在dispatch_async和dispatch_sysnc中更新UI时的区别

标签 ios multithreading grand-central-dispatch

比方说,我有一个名为 session 的 NSURLSession,我想在 downloadTaskWithRequest 中更新我的 UI。现在,情况 1 和情况 2 会发生什么:

情况 1:(dispatch_async)

NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];

NSURLSessionDownloadTask *task= [session downloadTaskWithRequest:request
completionHandler:^(NSURL *localFile, NSURLResponse *response, NSError *error){
    dispatch_async(dispatch_get_main_queue(), ^{
                    // UI Update    
                                               });
}];

情况2:(使用dispatch_sync)

NSURLSessionDownloadTask *task= [session downloadTaskWithRequest:request
completionHandler:^(NSURL *localFile, NSURLResponse *response, NSError *error){
    dispatch_sync(dispatch_get_main_queue(), ^{
                    // UI Update    
                                               });
}];

最佳答案

tl;dr 第二种情况将等待 UI 更新完成。首先更快。

详细

dispathc_sync 阻止当前队列上的执行,直到分派(dispatch)任务完成。因此,如果主队列上发生重大事件,情况二将需要很长时间才能完成。但是,当完成处理程序完成其工作时(例如,如果您在 UI 更新分派(dispatch)后执行某些操作),您可以确定 UI 已经更新。 此外,如果由于某种未知原因您将配置 session 以在主队列上分派(dispatch)完成 block ,那么在第二种情况下您将遇到死锁。这是因为主队列是串行的,这意味着它一次只执行一个任务 - 因此完成处理程序将等待 UI 更新完成,并且在完成处理程序未完成之前 UI 更新不会开始。

dispatch_async 不会阻塞执行流。这意味着,您不会以任何方式陷入死锁,并且完成 block 的执行时间将不依赖于 UI 更新持续时间。但是,即使完成处理程序完成,您也不知道 UI 更新是否完成。 但是,如果您的 completionHandler 分派(dispatch)到主队列,则更新的 UI 将仅在 completionHandler 完成后执行。

分割 情况二:

completionHandler:^(NSURL *localFile, NSURLResponse *response, NSError *error){
    //Some code
    //1
    dispatch_sync(dispatch_get_main_queue(), ^{
                    //2
                    // UI Update    
                    //3
                                               });
    //Some code
    //4
}];

到达//1、到达//2、到达//3、到达//4 。保证执行顺序。无论如何 - 无论它是这样还是根本不执行。

案例一:

completionHandler:^(NSURL *localFile, NSURLResponse *response, NSError *error){
    //Some code
    //1
    dispatch_async(dispatch_get_main_queue(), ^{
                    //2
                    // UI Update    
                    //3
                                               });
    //Some code
    //4
}];

到达//1。有保证。之后可能出现变体。 到达//2,到达//4,到达//3。 或者 到达//4,到达//2,到达//3 或者 到达//2,到达//3,到达//4

如果在主队列上分派(dispatch) completionBlock ,则第二个将始终如此。

如有不清楚的地方,请随时询问

关于ios - 在dispatch_async和dispatch_sysnc中更新UI时的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33809977/

相关文章:

ios - 在 UITableView 中插入一些行后,它不会在 ios 7 中滚动

ios - Appstore - 如何删除准备提交 tvOS

ios - 在 sprite 上启用触摸(spritekit)

java - 线程中的阻塞方法

java - ExecutorService 为每个提交的任务指定使用新线程

objective-c - 需要有关使用 GCD 将 block 添加到队列(objective-c)的建议

ios - 在 Swift SpriteKit 项目中播放声音?

java - 如何在 testNG 类中使用 completableFuture

multithreading - CLLocationmanager从后台线程更新

objective-c - 使用 dispatch_once