- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
这只是一个实验代码,但我很困惑,因为代码没有按我预期的那样执行。
代码如下:
- (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 invokingrunMode: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/
我如何在 dispatch_async 中正确调用 dispatch_async 调用 dispatch_group_t downloadQueue = dispatch_group_create()
我想按顺序添加一个 dispatch_async,但我不希望它们随机启动。我想举个例子: dispatch_async 1 开始... dispatch_async 1 结束。 dispatch_as
我正在尝试从 Firebase 下载一些带有图像的帖子并将其显示在我的表格 View 中。在下面的代码中,我注意到 tableview 仅在从 preLoadImage 函数调用下载每个图像后才加载。
我正在尝试学习 GCD,所以我还没有完全掌握它的工作原理。出于某种原因,我在调用以下方法后遇到帧率永久下降的情况。如果我不使用调度函数而只是在主循环中写入数据,帧速率将保持在 60。我不知道为什么。
我在将 JSON 数据存储到单个对象数组中时遇到问题。看起来问题出在处理 JSON 请求的 dispatch_asynch 的执行中。当我在方法之前创建一个断点而不是单步执行应用程序时,它似乎只是通过
我知道 dispatch_async 可以处理线程。 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
我有一个使用dispatch_async的函数: - (IBAction)action:(id)sender { int i=10000; NSString * data; d
我猜不到它的输出。 dispatch_async(serial_queue,^{NSlog(@"1");}); NSlog(@"2"); dispatch_async(serial_queue,^{N
NSString *firstID = @"https://wallpaperbrowse.com/media/images/soap-bubble-1958650_960_720.jpg"; 想象一
dispatch_queue_t queue = dispatch_queue_create("setup_cell", NULL); dispatch_async(queue, ^{ //L
我正在使用 here 的解决方案使 titleView clipsToBounds 始终为真。 我的 ViewController 中有这个并且运行良好,但是,如果我通过按后退按钮离开 ViewCon
我正在开发一个应用程序,我必须在其中从 JSON 获取数据并在 UITableView 中显示。正在后台获取数据。但它似乎进入了无限循环。 任何帮助将不胜感激。 - (UITableViewCell
我是 Swift 的新手,正在研究 dispatch_async 函数的工作原理。 API 文档显示 dispatch_async 有两个参数。但是,我可以传递一个参数,这没关系。 dispatch_
所以我运行了一段代码,我想提高性能,我注意到删除需要很长时间才能完成(大约 0.003 秒),所以我决定将它放入另一个线程,然后删除数组。 现在创建和运行线程所花费的时间比删除数组快得多,但是现在我创
我有以下代码... -(void) SetSerialNumber { NSLog(@"SetSerialNumber"); NSString *serialNum = textFie
假设我有以下代码: dispatch_async(dispatch_get_main_queue()) { myFunction() } 这表示异步调用调用 myFunction 的 bloc
我正在使用一些下载数据的代码。该代码使用 block 作为回调。有几种代码非常相似的下载方法:在回调 block 中,如果出现问题,它们会显示 UIAlertView。警报 View 始终如下所示:
我是 Swift 的新手,正在研究 dispatch_async 函数的工作原理。 API 文档显示 dispatch_async 有两个参数。但是,我可以传递一个参数,这没关系。 dispatch_
那么第一个问题就是dispatch_async是如何决定使用哪个线程的呢?只是随机选择它?我需要做一些解析和核心数据的事情,所以我不想阻塞 UI 线程并使用 dispatch_async,但在那之后我
假设我将任务异步分派(dispatch)到队列: { // we are on main queue dispatch_async(dispatch_get_global_queue(
我是一名优秀的程序员,十分优秀!