ChatGPT解决这个技术问题 Extra ChatGPT

了解 dispatch_async

我对这段代码有疑问

dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    NSData* data = [NSData dataWithContentsOfURL: 
      kLatestKivaLoansURL];
    [self performSelectorOnMainThread:@selector(fetchedData:) 
      withObject:data waitUntilDone:YES];
});

这段代码的第一个参数是

dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) 

我们是否要求此代码在其定义本身是返回给定优先级的全局并发队列的全局队列上执行串行任务?

与主队列相比,使用 dispatch_get_global_queue 有什么优势?

我很困惑。您能否帮助我更好地理解这一点。

你最好把你的代码分成几行,这样它就更有意义了。在 dispatch_queue_t myQueue 的变量类型中保护您的 dispatch_get_global_queue。仅将 myQueue 传递给您的“dispatch_async”更具可读性

L
Liftoff

在主队列上使用默认队列的主要原因是在后台运行任务。

例如,如果我正在从 Internet 下载文件并且我想更新用户的下载进度,我将在优先级默认队列中运行下载并异步更新主队列中的 UI。

dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
    //Background Thread
    dispatch_async(dispatch_get_main_queue(), ^(void){
        //Run UI Updates
    });
});

我理解大卫感谢您的回答,但我的问题更多的是理解这样做的逻辑,即要求此代码在全局队列上执行串行任务,全局队列本身就是并发队列
我正在按照您的建议做,但不知何故,当我在 Run UI Updates 中调用 [self.tableView reloadData] 时,uiTableViewCell 不会立即更新。大约需要 4 或 5 秒。这几天让我发疯了.
@GrandSteph 我对这种方法不太熟悉。也许该方法只需要 5 秒即可运行。 dispatch_async 的重要之处在于它允许您在后台执行操作而无需挂起主线程。
0 表示什么?
@Honey 0 是 flags 参数,目前绝对没有任何作用。来自文档:Flags that are reserved for future use. Always specify 0 for this parameter.
C
Cœur

所有 DISPATCH_QUEUE_PRIORITY_X 队列都是并发队列(意味着它们可以一次执行多个任务),并且在给定队列中的任务将使用“先进先出”顺序开始执行的意义上是 FIFO。这与主队列(来自 dispatch_get_main_queue())相比,主队列是一个串行队列(任务将按照接收到的顺序开始执行和完成执行)。

因此,如果您向 DISPATCH_QUEUE_PRIORITY_DEFAULT 发送 1000 个 dispatch_async() 块,这些任务将按照您将它们发送到队列中的顺序开始执行。对于 HIGH、LOW 和 Background 队列也是如此。您发送到任何这些队列中的任何内容都会在备用线程的后台执行,远离您的主应用程序线程。因此,这些队列适用于执行后台下载、压缩、计算等任务。

请注意,执行顺序是基于每个队列的 FIFO。因此,如果您将 1000 个 dispatch_async() 任务发送到四个不同的并发队列,将它们平均拆分并按顺序发送到 Background、LOW、DEFAULT 和 HIGH(即您将最后 250 个任务安排在 HIGH 队列上),很可能您看到的第一个任务将在该 HIGH 队列中,因为系统已经暗示这些任务需要尽快到达 CPU。

另请注意,我说“将按顺序开始执行”,但请记住,作为并发队列,事情不一定会根据每个任务的时间长度按顺序完成执行。

根据苹果:

https://developer.apple.com/library/content/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html

当您有多个可以并行运行的任务时,并发调度队列很有用。并发队列仍然是队列,因为它以先进先出的顺序出列任务;但是,并发队列可能会在任何先前的任务完成之前使其他任务出队。并发队列在任何给定时刻执行的实际任务数量是可变的,并且可以随着应用程序中条件的变化而动态变化。许多因素会影响并发队列执行的任务数量,包括可用内核的数量、其他进程正在完成的工作量以及其他串行调度队列中任务的数量和优先级。

基本上,如果您将这 1000 个 dispatch_async() 块发送到 DEFAULT、HIGH、LOW 或背景队列,它们都将按照您发送它们的顺序开始执行。但是,较短的任务可能会在较长的任务之前完成。这背后的原因是是否有可用的 CPU 内核,或者当前队列任务是否正在执行计算非密集型工作(从而使系统认为它可以并行调度其他任务而不管内核数量如何)。

并发级别完全由系统处理,并基于系统负载和其他内部确定的因素。这就是 Grand Central Dispatch(dispatch_async() 系统)的美妙之处——您只需将工作单元作为代码块,为它们设置优先级(基于您选择的队列),然后让系统处理其余的。

所以回答你上面的问题:你是部分正确的。您正在“要求该代码”以指定的优先级在全局并发队列上执行并发任务。块中的代码将在后台执行,并且任何其他(类似)代码将可能并行执行,具体取决于系统对可用资源的评估。

另一方面,“主”队列(来自 dispatch_get_main_queue())是一个串行队列(不是并发的)。发送到主队列的任务将始终按顺序执行,并且始终按顺序完成。这些任务也将在 UI 线程上执行,因此它适用于使用进度消息、完成通知等更新您的 UI。


+1,但我认为实际上并发队列是FIFO还是随机顺序并不重要。如果您在一个循环中启动 5 个任务,假设它们基本上会同时启动。不能保证例如第一个任务的第一个 I/O 操作将在第五个之前发生,即使它们执行相同的代码。 OTOH,对于串行队列,FIFO 行为是必不可少的,恕我直言,这是两种队列类型之间的定义差异。
难以置信的解释。鼓掌很多!
C
Community

斯威夫特版本

这是 David 的 Objective-C 答案的 Swift 版本。您使用全局队列在后台运行事物并使用主队列来更新 UI。

DispatchQueue.global(qos: .background).async {
    
    // Background Thread
    
    DispatchQueue.main.async {
        // Run UI Updates
    }
}

关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅