I've created a GCD queue like this:
我创建了一个GCD队列,如下所示:
dispatch_queue_t q = dispatch_queue_create("com.testcompany.myqueue", NULL);
When I dispatch tasks to that queue, it is way slower than simply executing the task on the main thread.
当我将任务分派到该队列时,这比简单地在主线程上执行任务要慢得多。
dispatch_async(q, ^(void) {
[self performHeavyCalculationAndUpdateUI];
});
My suspicion is that the queue has a very low priority by default. How can I change the priority of this queue? Or is there something else I must do?
我的猜测是队列默认的优先级很低。如何更改此队列的优先级?或者我还有别的事要做吗?
3 个解决方案
#1
7
If you're doing UIKit stuff, in your block that's running on the secondary queue, dispatch the UI updates back to the main queue from within the secondary queue via:
如果你在做UIKit的东西,在你的block中运行在辅助队列上,通过以下方式将UI更新从次要队列中发送回主队列:
dispatch_async(q, ^(void) {
[self performHeavyCalculationAndUpdateUI];
dispatch_async(dispatch_get_main_queue(), ^{
// do my ui update
});
});
Just dispatch the few lines that actually update the UI back to the main queue and you'll see it's not a matter of queue priorities, but rather just making sure that UI updates happen in main queue.
只需将实际更新UI的几行发送回主队列,您将看到这不是队列优先级的问题,而是确保UI更新在主队列中发生。
#2
43
Dispatch queues don't have a priority you can change.
分派队列没有可以更改的优先级。
You can change the target queue of your serial queues using the dispatch_set_target_queue
functions and use the DISPATCH_QUEUE_PRIORITY_HIGH
global queue. This just ensures that it will be scheduled before any other blocks enqueued on the queues with the default or low priority. Once your block starts executing it will not run faster or slower no matter what queue it was scheduled on.
您可以使用dispatch_set_target_queue函数更改串行队列的目标队列,并使用DISPATCH_QUEUE_PRIORITY_HIGH全局队列。这只是确保它将在任何其他块以默认或低优先级进入队列之前被调度。一旦您的块开始执行,无论它被安排在哪个队列上,它都不会运行得更快或更慢。
Your problem most likely is the updating of your GUI, see Robert Ryans answer.
您的问题很可能是GUI的更新,请参见Robert Ryans的回答。
#3
1
I think you're missing the point of asynchronous activities. And @RobertRyan's comment about UI updates not showing up quickly if performed on secondary queues is wrong. All UI updates need to be performed on the main queue. Period.
我认为您错过了异步活动的要点。@RobertRyan关于如果在辅助队列上执行UI更新不会很快出现的评论是错误的。所有UI更新都需要在主队列上执行。时期。
But back to GCD and the async queue. @Sven is right that you can't change the priority of the dispatch queues. Queues in GCD work in a FIFO (First In First Out) fashion, so the order you queue them up is the order they get performed in. This is part of why using GCD is thread-safe; you're guaranteed you won't run into any issues because of this FIFO queue priority. The second thing to understand is that when you dispatch_async a queue, the OS provides no guarantee of when that queue will be processed. It's a set-it-and-forget it type of process. If you need to know when the queue is done processing, you need to set up a completion block handler (you'll notice many of Apple's Frameworks have begun to implement this) to be notified of that. This is why Apple suggests nesting a dispatch_async call within your first dispatch_async call and requesting the main thread for UI updates. So, your code would look something like this:
但是回到GCD和异步队列。@Sven是对的,您不能更改分派队列的优先级。GCD中的队列以先进先出的方式工作,所以对它们进行排队的顺序就是它们执行的顺序。这就是为什么使用GCD是线程安全的一部分;您保证不会因为这个FIFO队列优先级而遇到任何问题。第二件要理解的事情是,当您分派一个队列时,操作系统不能保证该队列何时被处理。这是一种“定置不忘”的过程。如果您需要知道队列是何时完成的,您需要设置一个完成块处理程序(您会注意到许多苹果的框架已经开始实现这一点),以得到通知。这就是为什么苹果建议在第一个dispatch_async调用中嵌套dispatch_async调用并请求主线程进行UI更新。你的代码看起来是这样的:
dispatch_async(q, ^{
[self performHeavyCalculations];
dispatch_async(dispatch_get_main_queue, ^{
// some UI updates
});
});
Because of how GCD enqueues and dequeues, dispatching your UI updates asyncronously back to the main queue will allow for UI updates to occur without a perceptible delay to the user. If your UI updates depend on the result of performHeavyCalculations, you'll need to set up a completion handler or delegation scheme to notify the main queue of when this is complete so that the updates can occur. If the lag between the calculations and the update is too long, you may need to look into what you're doing in the calculations method that is taking so long.
由于GCD如何进行队列和去队列,异步地将UI更新发送回主队列将允许UI更新发生,而不会对用户造成明显的延迟。如果UI更新取决于performheavycalculation的结果,则需要设置一个完成处理程序或委托方案,以通知主队列何时完成,以便进行更新。如果计算和更新之间的延迟太长,您可能需要查看在计算方法中花费了如此长的时间。
#1
7
If you're doing UIKit stuff, in your block that's running on the secondary queue, dispatch the UI updates back to the main queue from within the secondary queue via:
如果你在做UIKit的东西,在你的block中运行在辅助队列上,通过以下方式将UI更新从次要队列中发送回主队列:
dispatch_async(q, ^(void) {
[self performHeavyCalculationAndUpdateUI];
dispatch_async(dispatch_get_main_queue(), ^{
// do my ui update
});
});
Just dispatch the few lines that actually update the UI back to the main queue and you'll see it's not a matter of queue priorities, but rather just making sure that UI updates happen in main queue.
只需将实际更新UI的几行发送回主队列,您将看到这不是队列优先级的问题,而是确保UI更新在主队列中发生。
#2
43
Dispatch queues don't have a priority you can change.
分派队列没有可以更改的优先级。
You can change the target queue of your serial queues using the dispatch_set_target_queue
functions and use the DISPATCH_QUEUE_PRIORITY_HIGH
global queue. This just ensures that it will be scheduled before any other blocks enqueued on the queues with the default or low priority. Once your block starts executing it will not run faster or slower no matter what queue it was scheduled on.
您可以使用dispatch_set_target_queue函数更改串行队列的目标队列,并使用DISPATCH_QUEUE_PRIORITY_HIGH全局队列。这只是确保它将在任何其他块以默认或低优先级进入队列之前被调度。一旦您的块开始执行,无论它被安排在哪个队列上,它都不会运行得更快或更慢。
Your problem most likely is the updating of your GUI, see Robert Ryans answer.
您的问题很可能是GUI的更新,请参见Robert Ryans的回答。
#3
1
I think you're missing the point of asynchronous activities. And @RobertRyan's comment about UI updates not showing up quickly if performed on secondary queues is wrong. All UI updates need to be performed on the main queue. Period.
我认为您错过了异步活动的要点。@RobertRyan关于如果在辅助队列上执行UI更新不会很快出现的评论是错误的。所有UI更新都需要在主队列上执行。时期。
But back to GCD and the async queue. @Sven is right that you can't change the priority of the dispatch queues. Queues in GCD work in a FIFO (First In First Out) fashion, so the order you queue them up is the order they get performed in. This is part of why using GCD is thread-safe; you're guaranteed you won't run into any issues because of this FIFO queue priority. The second thing to understand is that when you dispatch_async a queue, the OS provides no guarantee of when that queue will be processed. It's a set-it-and-forget it type of process. If you need to know when the queue is done processing, you need to set up a completion block handler (you'll notice many of Apple's Frameworks have begun to implement this) to be notified of that. This is why Apple suggests nesting a dispatch_async call within your first dispatch_async call and requesting the main thread for UI updates. So, your code would look something like this:
但是回到GCD和异步队列。@Sven是对的,您不能更改分派队列的优先级。GCD中的队列以先进先出的方式工作,所以对它们进行排队的顺序就是它们执行的顺序。这就是为什么使用GCD是线程安全的一部分;您保证不会因为这个FIFO队列优先级而遇到任何问题。第二件要理解的事情是,当您分派一个队列时,操作系统不能保证该队列何时被处理。这是一种“定置不忘”的过程。如果您需要知道队列是何时完成的,您需要设置一个完成块处理程序(您会注意到许多苹果的框架已经开始实现这一点),以得到通知。这就是为什么苹果建议在第一个dispatch_async调用中嵌套dispatch_async调用并请求主线程进行UI更新。你的代码看起来是这样的:
dispatch_async(q, ^{
[self performHeavyCalculations];
dispatch_async(dispatch_get_main_queue, ^{
// some UI updates
});
});
Because of how GCD enqueues and dequeues, dispatching your UI updates asyncronously back to the main queue will allow for UI updates to occur without a perceptible delay to the user. If your UI updates depend on the result of performHeavyCalculations, you'll need to set up a completion handler or delegation scheme to notify the main queue of when this is complete so that the updates can occur. If the lag between the calculations and the update is too long, you may need to look into what you're doing in the calculations method that is taking so long.
由于GCD如何进行队列和去队列,异步地将UI更新发送回主队列将允许UI更新发生,而不会对用户造成明显的延迟。如果UI更新取决于performheavycalculation的结果,则需要设置一个完成处理程序或委托方案,以通知主队列何时完成,以便进行更新。如果计算和更新之间的延迟太长,您可能需要查看在计算方法中花费了如此长的时间。