我创建了一个像这样的GCD队列:
dispatch_queue_t q = dispatch_queue_create("com.testcompany.myqueue", NULL);
当我将任务分派到该队列时,它比在主线程上执行任务要慢。
dispatch_async(q, ^(void) {
[self performHeavyCalculationAndUpdateUI];
});
我怀疑默认情况下队列的优先级非常低。 如何更改此队列的优先级?或者我还有其他必须做的事情吗?
答案 0 :(得分:43)
调度队列没有您可以更改的优先级。
您可以使用dispatch_set_target_queue
函数更改串行队列的目标队列,并使用DISPATCH_QUEUE_PRIORITY_HIGH
全局队列。这只是确保它将在具有默认或低优先级的队列中排队的任何其他块之前进行调度。一旦你的块开始执行,无论它安排在哪个队列,它都不会运行得更快或更慢。
您的问题很可能是更新您的GUI,请参阅Robert Ryans的回答。
答案 1 :(得分:7)
如果您正在执行UIKit,那么在您在辅助队列中运行的块中,通过以下方式将UI更新从辅助队列中调回主队列:
dispatch_async(q, ^(void) {
[self performHeavyCalculationAndUpdateUI];
dispatch_async(dispatch_get_main_queue(), ^{
// do my ui update
});
});
只需将实际更新UI的几行调度回主队列,您将看到它不是队列优先级问题,而只是确保在主队列中发生UI更新。
答案 2 :(得分:1)
我认为你错过了异步活动的重点。 @ RobertRyan关于UI更新的评论如果在辅助队列上执行则不会很快显示错误。需要在主队列上执行所有UI更新。周期。
但回到GCD和异步队列。 @Sven是对的,你不能改变调度队列的优先级。 GCD中的队列以FIFO(先进先出)方式工作,因此排队的顺序是它们执行的顺序。这是使用GCD线程安全的部分原因。您可以保证,由于此FIFO队列优先级,您不会遇到任何问题。要理解的第二件事是,当你dispatch_async一个队列时,操作系统不能保证何时处理该队列。它是一种设置 - 忘记它的过程类型。如果您需要知道队列何时完成处理,您需要设置一个完成块处理程序(您将注意到许多Apple的框架已经开始实现这一点)以获得通知。这就是为什么Apple建议在您的第一个dispatch_async调用中嵌套dispatch_async调用并请求主线程进行UI更新。所以,你的代码看起来像这样:
dispatch_async(q, ^{
[self performHeavyCalculations];
dispatch_async(dispatch_get_main_queue, ^{
// some UI updates
});
});
由于GCD如何排队和出列,将您的UI更新异步调度回主队列将允许UI更新发生而不会对用户造成明显的延迟。如果UI更新取决于performHeavyCalculations的结果,则需要设置完成处理程序或委派方案,以通知主队列何时完成,以便可以进行更新。如果计算和更新之间的延迟太长,您可能需要查看您在计算方法中所做的事情,这需要花费很长时间。