首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在主线程上执行耗时的操作如何影响用户界面刷新?

在主线程上执行耗时的操作如何影响用户界面刷新?
EN

Stack Overflow用户
提问于 2019-05-21 15:38:09
回答 3查看 216关注 0票数 1

主线程上的同步时间会导致主线程阻塞。这是UI延迟的原因吗?如果我在主线程上执行异步、耗时的操作,这会影响主线程上UI的流吗?同样,耗时的操作必须放在子线程异步操作中.

  1. 视图刷新代码在执行之前等待一个耗时的操作完成,这是UI不流动的原因吗? NSThread detachNewThreadSelector:@selector(syncMain) toTarget:selector: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;//模拟耗时操作NSLog(@“1-%”,NSThread currentThread);//在主线程}}上);self.testImage=UIImage imageNamed:xxx;//等待一个耗时的操作完成,从而导致UI刷新块}
  2. 在主线程上执行异步耗时操作会影响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;//模拟耗时操作NSLog(@“1-%@”,NSThread currentThread);//在主线程上,也}};self.testImage=UIImage映像名称:xxx;//立即执行代码}
  1. 是否只能在子线程上异步执行耗时的操作以保持UI的完整性?
  • (void)asyncChild {asyncChild{xxx;//模拟dispatch_async(dispatch_get_main_queue(),{ self.testImage=UIImage图像)};}
EN

回答 3

Stack Overflow用户

发布于 2019-05-21 15:44:45

你能举个例子说明你有问题的一些操作吗?

如果主线程忙着做其他事情而不是UI发布的事情,那么是的,您可能会经历一个缓慢的或不可用的UI。

通常情况下,应该在后台线程上执行耗时或同步的操作,以避免出现此问题。但是,请注意,UI/UIKit相关操作必须在主线程上执行,否则应用程序可能会崩溃。

票数 0
EN

Stack Overflow用户

发布于 2019-05-21 15:45:00

如果您在主线程上并向异步线程分派一些东西,则除非该线程正在消耗设备上的所有资源,否则它不会对UI产生影响。

但是,当您完成异步线程并使用异步操作的结果更新UI时,您将得到什么。如果忘记将UI更新移到主线程上,UI可能会在某个随机时间间隔更新,或者根本不会更新。这就是大多数人在进行异步操作时得到的好处。

票数 0
EN

Stack Overflow用户

发布于 2019-05-21 17:14:54

通常,异步地向后台队列分配某些内容不会对UI产生实质性影响。这正是我们这么做的原因,以尽量减少对UI的影响。

如果你看到了滞后,这可能会发生在:

  • 后台线程意外地执行了一些UI更新,忽略了将其分派回主线程;
  • 后台作业将一些级联的任务分派到并发全局队列中,耗尽了可用的非常有限的工作线程;
  • 异步作业本身就是将主线程用于任何耗时的事情,或者
  • 后台任务非常紧张,以至于消耗了所有系统资源(这是非常不寻常的)。

在编辑中,您提供了一些示例:

  1. 视图刷新代码在执行之前等待一个耗时的操作完成,这是UI不流动的原因吗? NSThread detachNewThreadSelector:@selector(syncMain) toTarget:selector: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;//模拟耗时操作NSLog(@“1-%”,NSThread currentThread);//在主线程}}上);self.testImage=UIImage imageNamed:xxx;//等待一个耗时的操作完成,从而导致UI刷新块}

当您将块分派回主线程时,您不希望包含这些耗时的任务,否则会对UX产生不利影响。在发送到主队列之前,在后台线程上执行这些耗时的任务。

代码语言:javascript
运行
复制
[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 (就像您的第三个例子):

代码语言:javascript
运行
复制
- (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
        });
    });
}

  1. 在主线程上执行异步耗时操作会影响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;//模拟耗时操作NSLog(@“1-%@”,NSThread currentThread);//在主线程上,也}};self.testImage=UIImage映像名称:xxx;//立即执行代码}

异步地将其分派到主线程vs的事实是不重要的。问题不在于如何分配到主队列,而在于您分派了什么。分派给主线程的代码有一些慢任务,这意味着主线程在发生慢任务时不能做任何其他事情。这就是对UI产生不利影响的原因。

因此,解决方案与上面一样,您希望在分派到主队列之前执行这些耗时的任务。虽然从主线程的角度来看,同步或异步分派并不重要,但我们通常倾向于异步进行。同样,为什么后台线程需要坐在那里等待UI更新完成。

  1. 是否只能在子线程上异步执行耗时的操作以保持UI的完整性?
  • ( dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{ NSThread睡眠sleepForTimeInterval:2;//模拟耗时操作dispatch_async(dispatch_get_main_queue(),^{ self.testImage=UIImage imageNamed:xxx;});}

对,是这样。我建议您使用第三种模式,并从代码中完全删除detachNewThreadSelector。坚持GCD。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56241811

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档