Как правило, отправка чего-либо асинхронно в фоновую очередь не оказывает существенного влияния на пользовательский интерфейс.Именно поэтому мы делаем это, чтобы минимизировать влияние на пользовательский интерфейс.
Если вы видите отставание, это может произойти, если:
фоновый поток случайно выполнил некотороеОбновление пользовательского интерфейса, игнорируя отправку этого обратно в основной поток;
фоновое задание отправило несколько каскадных серий задач в параллельные глобальные очереди, исчерпав очень ограниченные доступные рабочие потоки;
асинхронное задание само по себе использует основной поток для чего-либо требующего много времени, или
фоновая задача была настолько интенсивной, что потребляла все системные ресурсы(что крайне необычно).
В вашем редакторе вы приводите несколько примеров:
Является ли обновление представлениякод ожидает завершения трудоемкой операции, прежде чем она может быть выполнена, причина того, что пользовательский интерфейс не работает?
[NSThread detachNewThreadSelector:@selector(syncMain) toTarget:self withObject:nil];
- (void)syncMain {
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_sync(queue, ^{
// 追加任务1
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // Simulated time-consuming operation
NSLog(@"1---%@",[NSThread currentThread]); // on the main thread
}
});
self.testImage=[UIImage imageNamed:xxx];//Waiting for a time-consuming operation to complete, causing a UI refresh block
}
Когда вы отправляете блок обратно на главнуюнить, ты делаешьне хотите включать эти трудоемкие задачи, иначе вы будете отрицательно влиять на UX.Выполняйте эти трудоемкие задачи в фоновом потоке перед отправкой в основную очередь.
[NSThread detachNewThreadSelector:@selector(asyncMain) toTarget:self withObject:nil];
- (void)asyncMain {
dispatch_queue_t queue = dispatch_get_main_queue();
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // Simulated time-consuming operation
NSLog(@"1---%@",[NSThread currentThread]); // still on the background thread
}
dispatch_async(queue, ^{
self.testImage=[UIImage imageNamed:xxx];//Execute code now
});
}
И нет причин синхронно отправлять обновления обратно в основную очередь.Отправляйте эти обновления асинхронно. Почему фоновый поток ожидает завершения обновления пользовательского интерфейса?
Лично я бы предложил исключить detachNewThreadSelector
и просто придерживаться GCD (как в третьем примере):
- (void)someTaskAndUpdateUI {
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // Simulated time-consuming operation
NSLog(@"1---%@",[NSThread currentThread]); // but on background queue
}
dispatch_async(dispatch_get_main_queue(), ^{
self.testImage=[UIImage imageNamed:xxx];//Execute code now
});
});
}
Влияет ли выполнение асинхронных длительных операций в главном потоке на текучесть пользовательского интерфейса?
- (void)asyncMain {
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_async(queue, ^{
// 追加任务1
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // Simulated time-consuming operation
NSLog(@"1---%@",[NSThread currentThread]); // on the main thread,too
}
});
self.testImage=[UIImage imageNamed:xxx];//Execute code now
}
Тот факт, что вы отправили это асинхронно в основной потокпротив синхронно несущественно.Вопрос не в том, как вы отправили в основную очередь, а в том, что вы отправили.Код, который вы отправили в основной поток, имеет некоторую медленную задачу, то есть основной поток не может делать ничего другого, пока эта медленная задача происходит.Это то, что отрицательно влияет на пользовательский интерфейс.
Таким образом, решение такое же, как и выше, где вы хотите выполнить те трудоемкие задачи перед отправкой в основную очередь.И хотя с точки зрения основного потока не имеет значения, будете ли вы отправлять данные синхронно или асинхронно, мы обычно предпочитаем асинхронно.Снова, почему фоновый поток должен сидеть там в ожидании завершения обновления пользовательского интерфейса.
Могут ли трудоемкие операции выполняться только в дочерних потоках асинхронно, чтобы сохранить целостность интерфейса?
- (void)asyncChild {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[NSThread sleepForTimeInterval:2]; // Simulated time-consuming operation
dispatch_async(dispatch_get_main_queue(), ^{
self.testImage=[UIImage imageNamed:xxx];
});
});
}
Исправить.И я бы посоветовал вам использовать этот третий шаблон и полностью исключить detachNewThreadSelector
из вашего кода.Палка с GCD.