gpt4 book ai didi

ios - 为什么我不能停止 dispatch_async 串行队列中的计时器?

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:28:59 26 4
gpt4 key购买 nike

这只是一个实验代码,但我很困惑,因为代码没有按我预期的那样执行。

代码如下:

- (void)viewDidLoad {
[super viewDidLoad];
self.myQueue = dispatch_queue_create("com.maxwell.timer", NULL);
dispatch_async(self.myQueue, ^{
self.timer = [NSTimer timerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {
NSLog(@"Hey!");
}];
[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] run];
});
}

现在,我得到了一个输出“嘿!”每 1 秒一次,这里没问题。我知道在分派(dispatch)的线程中我必须显式运行 runloop。

当我试图停止计时器时,问题出现了。

- (void)stopTimer { 
dispatch_async(self.myQueue, ^{
[self.timer invalidate];
self.Timer = nil;
});
}

实际上 block 中的代码甚至不会执行!

另外,如果我这里使用并发队列(dispatch_asyn(dispatch_get_global_queue(...), ^{...}))就可以了。

我知道的事情:每次我dispatch_async,无论并发队列还是串行队列,代码都在不同的线程中执行。所以严格来说,我没有在我添加它的同一线程中使计时器失效,但它确实在并发线程中失效。

所以我的问题是为什么它在串行队列中无法失效?

最佳答案

问题是您有一个串行队列,您可以在该队列上调用 [[NSRunLoop currentRunLoop] run] .但是您不会从该调用返回(只要该运行循环上有计时器等)。作为run documentation说:

If no input sources or timers are attached to the run loop, this method exits immediately; otherwise, it runs the receiver in the NSDefaultRunLoopMode by repeatedly invoking runMode:beforeDate:. In other words, this method effectively begins an infinite loop that processes data from the run loop’s input sources and timers.

这会阻塞串行队列的线程。只要该线程被阻塞,分派(dispatch)到该队列的任何代码(例如您尝试使计时器无效)都不会运行。你有一个“第 22 条军规”。

最重要的是,如果您要设置后台线程来运行 NSTimer,您需要为此创建自己的线程,而不是使用 GCD worker线程。参见 https://stackoverflow.com/a/38031658/1271826举个例子。但正如该答案继续描述的那样,在后台线程上运行计时器的首选方法是调度计时器,让您摆脱操纵线程和运行循环的杂草。

关于ios - 为什么我不能停止 dispatch_async 串行队列中的计时器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52315181/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com