我正在尝试通过iOS中的GCD同时在后台加载两组数据。目前,我构建了两个不同的并发队列,其中我运行每个任务。但是,第一个队列的完成和第二个队列(运行相同密集型任务)之间的延迟非常大(因此我假设它们没有并发运行)。你们有什么建议来解决这个问题吗?我不完全理解接近这个的正确方法。谢谢!
dispatch_queue_t myQueue = dispatch_queue_create("com.a.identifier", DISPATCH_QUEUE_CONCURRENT);
dispatch_queue_t myQueue2 = dispatch_queue_create("com.a.identifier2", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(myQueue, ^{
[self fetchDataWithDataFromUrl:[NSURL URLWithString:linkOne]];
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
});
dispatch_async(myQueue2, ^{
[self fetchDataWithDataFromUrl2:[NSURL URLWithString:linkTwo]];
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
});
答案 0 :(得分:4)
他们很可能同时运行。它们可能不是并行运行的。 It's important to know the difference. GCD提供并发性,它对并行性做出的承诺很少。许多图书馆都是如此(通常是更重要的特征)。
您有多少个核心?如果你只有一个核心,那么如果第二个工作等待第一个工作完成就不足为奇了。如果你有两个核心,但主队列有很多工作,那么它可能会在你的一个块之前获得优先级。您应该使用Instruments中的GCD工具来探索事情的安排(printf
在这里也是一个强大的工具)。请记住,上下文切换需要时间。要在核心上获得最佳吞吐量,您希望在其上运行一件事直到该事情完成,然后运行下一件事。来回切换以使它们一起完成将使它们两者运行得更慢。大多数系统偏向于吞吐量。没有理由换掉一个块来运行一个具有相同优先级的块。
你知道这两个工作同时得到他们的数据吗?如果您从网络中撤出,很可能一个人比另一个人更快或更快地到来。您可能在单个连接上进行流水线操作,这可能会序列化您的网络流量。您应该在数据到达时记录。您还应该在块实际启动时进行记录(将printf()
放在块的顶部)。
如果您需要第一个作业在更新UI之前等待第二个作业完成,那么您应该将两个作业都放到dispatch_group中,以便reloadData
等待它们。
你真的需要深入了解正在运行的内容和时间。这种症状有时可能意味着您在其他地方的后台线程上更新UI。这可能导致获得正确更新的长时间延迟(可能与此代码无关)。放入printf()
语句并使用工具非常重要,以确保您了解实际情况。
如果节奏比吞吐量更重要(您建议的话),您可能希望将您的工作分成更小的部分并进行交错。