全局队列中的计时器未在iOS中调用 [英] Timer inside global queue is not calling in 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屋!