主线程上的同步时间可能导致主线程阻塞。这是UI延迟的原因吗?如果我正在主线程上执行异步,耗时的操作,这是否会影响主线程上的UI流程?同样,必须将耗时的操作放在子线程异步操作中。
视图刷新代码是否正在等待耗时的操作完成才能执行,原因是UI不流畅?
[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
}
在主线程上执行异步耗时的操作是否会影响UI的流动性?
- (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
}
是否只能在子线程上异步执行耗时的操作以保持UI完整?
- (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];
});
});
}
答案 0 :(得分:0)
您能举例说明遇到问题的某些操作吗?
如果主线程忙于做其他事情而不是UI相关的事情,那么是的,您可能会遇到缓慢或无法使用的UI。
通常,应该在后台线程上执行耗时或同步的操作,以避免此问题。但是请注意,必须在主线程上执行与UI / UIKit相关的操作,否则您的应用程序可能会崩溃。
答案 1 :(得分:0)
如果您在主线程上并向异步线程分派一些东西,那么除非该线程消耗了设备上的所有资源,否则它不会对UI产生影响。
当异步线程完成后,您将使用异步操作的结果更新UI,这将使您满意。如果您忘记将UI更新移到主线程上,则UI可能会在某个随机时间间隔更新,或者根本不会更新。这就是大多数人进行异步操作时得到的。
答案 2 :(得分:0)
通常,异步分发一些东西到后台队列不会对UI产生实质性影响。这就是我们这样做的原因,以最大程度地减少对用户界面的影响。
如果您看到时滞,则可能发生在以下情况:
后台线程意外执行了一些UI更新,忽略了将其分派回主线程;
后台作业将一系列级联的任务调度到并发的全局队列中,耗尽了非常有限的可用工作线程;
异步作业本身就是使用主线程进行任何耗时的操作,或者
后台任务非常繁琐,以至于耗尽了所有系统资源(这是非常不寻常的)。
在编辑中,提供一些示例:
视图刷新代码是否正在等待耗时的操作完成才能执行,原因是UI不流畅?
[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
});
}
并且没有理由将更新同步发送回主队列。异步分发这些更新,为什么后台线程要等待UI更新完成?
我个人建议不要使用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
});
});
}
在主线程上执行异步耗时的操作是否会影响UI的流动性?
- (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 }
您异步地将其分派到主线程而不是同步地分派的事实是无关紧要的。问题不在于您如何分配到主队列,而在于您分配了什么。您分派给主线程的代码执行的任务很慢,这意味着在执行慢任务时主线程无法执行其他任何操作。那就是对用户界面造成不利影响的原因。
因此解决方案与上面的解决方案一样,您要在将这些耗时的任务分派到主队列之前执行这些任务。尽管从主线程的角度来看,是同步还是异步调度都没有关系,但我们通常更喜欢异步调度。同样,为什么后台线程需要坐在那里等待UI更新完成。
是否只能在子线程上异步执行耗时的操作以保持UI完整?
- (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。