全局队列中的计时器未在iOS中调用 [英] Timer inside global queue is not calling in iOS

查看:87
本文介绍了全局队列中的计时器未在iOS中调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

-(void)viewDidLoad{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [NSTimer scheduledTimerWithTimeInterval:0.10 
                                         target:self 
                                       selector:@selector(action_Timer) 
                                       userInfo:nil 
                                        repeats:YES];
        }
    );
}

-(void)action_Timer{
    LOG("Timer called");
}

action_Timer没有被调用.我不知道为什么.你有什么主意吗?

action_Timer is not being called. I dont know why. Do you have any idea?

推荐答案

您正在从GCD工作线程调用+[NSTimer scheduledTimerWithTimeInterval:...]. GCD工作线程不会运行运行循环.这就是为什么您的第一次尝试无效的原因.

You're calling +[NSTimer scheduledTimerWithTimeInterval:...] from a GCD worker thread. GCD worker threads don't run a run loop. That's why your first try didn't work.

尝试[[NSRunLoop mainRunLoop] addTimer:myTimer forMode:NSDefaultRunLoopMode]时,您是从GCD工作线程向主运行循环发送消息. NSRunLoop存在的问题不是线程安全的. (这在

When you tried [[NSRunLoop mainRunLoop] addTimer:myTimer forMode:NSDefaultRunLoopMode], you were sending a message to the main run loop from a GCD worker thread. The problem there is NSRunLoop is not thread-safe. (This is documented in the NSRunLoop Class Reference.)

相反,您需要分派回主队列,以便在将addTimer:...消息发送到主运行循环时,它在主线程上完成.

Instead, you need to dispatch back to the main queue so that when you send the addTimer:... message to the main run loop, it's done on the main thread.

-(void)viewDidLoad {
    [super viewDidLoad];
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSTimer *timer = [NSTimer timerWithTimeInterval:0.10 
                                         target:self 
                                       selector:@selector(action_Timer) 
                                       userInfo:nil 
                                        repeats:YES];
        dispatch_async(dispatch_get_main_queue(), ^{
            [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
        });        
    });
}

实际上,如果要在主运行循环中安排计时器,则没有理由在后台队列上创建计时器.您可以只调度回主队列来创建和调度它:

Realistically, there's no reason to create the timer on the background queue if you're going to schedule it in the main run loop. You can just dispatch back to the main queue to create and schedule it:

-(void)viewDidLoad {
    [super viewDidLoad];
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"on background queue");
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"on main queue");
            [NSTimer scheduledTimerWithTimeInterval:0.10 
                                         target:self 
                                       selector:@selector(action_Timer) 
                                       userInfo:nil 
                                        repeats:YES];
        });        
    });
}

请注意,我的两个解决方案都将计时器添加到主运行循环中,因此计时器的操作将在主线程上运行.如果您希望计时器的操作在后台队列上运行,则应从该操作中将其分派给它:

Note that both of my solutions add the timer to the main run loop, so the timer's action will run on the main thread. If you want the timer's action to run on a background queue, you should dispatch to it from the action:

-(void)action_Timer {
    // This is called on the main queue, so dispatch to a background queue.
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        LOG("Timer called");
    });
}

这篇关于全局队列中的计时器未在iOS中调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆