- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我正在尝试理解 RunLoops 的概念。我已经阅读了关于 RunLoops 的 Apple 开发人员指南,并且在一定程度上理解了 RunLoops 的概念。为了让我的概念更清晰,我写了一个非常简单的代码,其中使用了 RunLoops。代码如下所示。
- (void)viewDidLoad
{
[super viewDidLoad];
thread = [[NSThread alloc] initWithTarget:self selector:@selector(testMethod) object:nil];
[thread start];
}
- (void)testMethod {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSLog(@"Thread Entered");
NSMachPort* dummyPort = [[NSMachPort alloc] init];
[[NSRunLoop currentRunLoop] addPort:dummyPort forMode:NSDefaultRunLoopMode];
while(!exitThread) {
NSLog(@"Thread did some work");
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
[[NSRunLoop currentRunLoop]
removePort:dummyPort
forMode:NSDefaultRunLoopMode];
[dummyPort release];
NSLog(@"Thread Exited");
[pool drain];
}
- (IBAction)doDomeWorkOnBackgroundThread:(id)sender {
[self performSelector:@selector(dummyMethod) onThread:thread withObject:nil waitUntilDone:NO];
}
- (IBAction)exitThread:(id)sender {
[self performSelector:@selector(exitBackgroundThread) onThread:thread withObject:nil waitUntilDone:NO];
}
- (void)exitBackgroundThread {
exitThread = YES;
}
- (void)dummyMethod {
//Empty
}
在上面的代码中,我正在创建一个后台线程,并在该后台线程上调用函数 testMethod
。在 testmethod
中,我正在运行一段时间,检查 BOOL 变量 exitThread
并使用 - (BOOL)runMode: beforeDate:
运行后台线程的 RunLoop NSRunLoop 的方法。有两个 IBAction 附加到两个按钮。正如 IBAction 的名称所示,其中一个是 exitThread
,另一个是唤醒线程并执行 while 循环中编写的 NSLog 语句。
上面的代码如我所料运行。每当执行 doDomeWorkOnBackgroundThread
方法时,线程就会从其运行循环中唤醒,执行 while 循环的下一次迭代,检查 BOOL 变量 exitThread
并在找到它时将其值设置为 false 进入while 循环并执行 NSlog 语句。类似地,当执行 exitThread:
方法时,exitThread
变量设置为 true,这会导致 while 循环和线程退出。
但是我需要更多的说明:
1) 如果不是在 while 循环中使用 runMode: beforeDate:
,而是使用 NSRunLoop 的 run
或 runUntilDate:
方法,那么当执行 exitThread:
方法时,线程永远不会退出。 exitBackgroundThread 方法在后台线程上调用,但 while 循环从不执行它的下一次迭代(就像我使用 runMode: beforeDate:
时那样),因此线程永远不会退出。
2) 我尝试将 exitBackgroundThread
方法更改为
- (void)exitBackgroundThread {
exitThread = YES;
CFRunLoopStop(CFRunLoopGetCurrent());
}
因为 exitBackgroundThread
是在后台线程上执行的,所以 CFRunLoopGetCurrent() 应该给出后台线程的 RunLoop。因此,无论我使用何种 NSRunLoop 方法启动 RunLoop,这应该理想地停止后台线程的运行循环。所以在任何情况下线程都必须在调用上述函数时退出。但这并没有发生。
我知道我在这里遗漏了一些东西,并且我正在做大量的谷歌搜索以找到这个问题的答案,但似乎找不到正确的答案。
**编辑
我找到了 this与我的第一个查询非常相似的问题。它在很大程度上消除了我的第一个疑问。
最佳答案
您在使用 run
或 runUntilDate:
而不是 runMode:beforeDate:
时看到的变化是预期的。 runMode:beforeDate:
的文档是这样说的:
it returns after either the first input source is processed or
limitDate
is reached.
有一个输入源负责处理performSelector:...
请求。因此,当您发送 performSelector:...
时,运行循环会处理一个输入源,然后返回。
另一方面,run
的文档是这样说的:
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.
因此,在运行循环处理完您的 performSelector:...
请求的输入源后,它会等待另一个输入源准备就绪。它不会返回。由于它不返回,您的 while
循环永远没有机会测试 exitThread
。
您尝试使用 CFRunLoopStop
是个好主意,但不幸的是,run
的文档是这样说的:
If you want the run loop to terminate, you shouldn't use this method. Instead, use one of the other run methods and also check other arbitrary conditions of your own, in a loop.
所以你不能依赖CFRunLoopStop
来让run
返回。
相反,您可以降低到较低级别并使用 CFRunLoopRun
运行运行循环,因为记录了 CFRunLoopStop
以使该函数返回:
This function forces
rl
to stop running and return control to the function that calledCFRunLoopRun
orCFRunLoopRunInMode
for the current run loop activation.
所以试试这个来运行你的运行循环:
while(!exitThread) {
NSLog(@"Thread did some work");
CFRunLoopRun([NSRunLoop currentRunLoop].getCFRunLoop);
}
关于objective-c - NSRunLoop- 需要澄清,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18259708/
崩溃发生在以下代码中: void CocoaCommRequest::launchSync() { launchAsync(); while (![_delegate finished
我的 iPhone 应用程序中有几个选项卡,需要几秒钟的时间才能加载(从本地 sqlite 数据库中提取大量数据)。当用户触摸选项卡时,应用程序似乎什么也没做。我试图放置一个显示旋转器的窗口,但是由于
我开始将 RunLoop 理解为类似于 Java 中的事件队列。我现在尝试做的 Wgat,只是为了更好地理解,是在运行自己的 RunLoop 的应用程序中创建一个后台线程。我在示例 ViewContr
我制作了一个带有计时器的 RunLoop,该计时器更新显示倒计时的标签。我需要 RunLoop 在倒计时达到零时停止,对于计时器正常完成的情况,我可以使用 runUntilDate,日期为当前日期 +
我在线程中有一个连接,因此我将其添加到运行循环中以获取所有数据: [[NSRunLoop currentRunLoop] run]; [connection scheduleInRunLoop
我有一个每 5 分钟调用一次的后台方法。 该方法使用NSURLConnection将数据发送到 Web 服务。 在那种方法中,我有这个代码: ... conn = [[NSURLConnection
我对 NSRunLoop 的实现很感兴趣,它可以在不占用大量 CPU 的情况下让线程空闲/休眠。这在 Objective-c 中是如何实现的?消耗高 CPU 的简单解决方案是 while(YES) {
在我的应用程序中,我需要对 restful web api 进行 https 调用并在返回时处理结果。同时服务调用的数量从来都不是固定的,因此相应地编写了相关代码。从服务获取的数据临时存储在应用程序内
我在自定义单元格上使用 NSTimer 运行 NSRunLoop 以持续更新“有效至”UILabel。它工作正常,直到我关闭 tableView,NSRunLoop 继续倒计时。我使用 dealloc
我不太清楚 NSRunLoop 是否线程安全。所以我需要澄清一下它是否线程安全,为什么? 任何帮助都是可观的。 最佳答案 在 NSRunLoop 的开头有一个警告 official reference
谁能解释一下什么是NSRunLoop?据我所知,NSRunLoop 是与 NSThread 相关的东西,对吗?所以假设我创建了一个像 这样的线程 NSThread* th=[[NSThread all
我刚刚在我的 ViewController 中使用 NSRunLoop 和 NSTimer 创建了一个带计时器的后台任务: - (void)runBackgroundTask: (int) time{
我读了很多关于 NSRunLoop 的帖子,比如 this , this , this .但无法弄清楚 NSRunLoop 实际上做了什么 我平时看到的是工作线程 wthread = [[NSThre
谁能解释什么是NSRunLoop?所以据我所知 NSRunLoop 是与 NSThread 相关的东西,对吗?所以假设我创建了一个像 这样的线程 NSThread* th=[[NSThread all
我试图在守护进程结束时或者有人退出该进程时释放在守护进程中分配的资源。 可以说, int main(int argc, const char * argv[]) { Controller *c
在 Cocoa 应用程序中,运行如下代码: NSDate* date = [NSDate dateWithTimeIntervalSinceNow:30.0]; while (date.timeInt
我买了《Big Nerd Ranch Guide for Objective-C》,但有一些关于 NSRunLoop 的内容我不明白。 这是书中的一段代码: NSTimer *timer = [NST
假设我有 2 个线程,一个是主线程,另一个是辅助线程。主线程使用最多,但有时(很少)我希望辅助线程根据主线程的调用执行一些工作。大多数时候辅助线程应该休眠。现在,经过一番搜索,我明白做到这一点的方法是
我正在编写一个应用程序,它必须与通过 USB 连接的设备进行通信。该应用程序按固定时间轮流从设备发送和接收数据。所有 Rx/Tx 都发生在单独的线程中,否则 UI 将被阻塞。基本结构基本上是这样的。
我正在使用 NSUrlConnection 来发出 http 请求。我想避免使用事件驱动代码,所以我通过以下方式使用 NSRunloop: NSURLRequest *request = [[NSUR
我是一名优秀的程序员,十分优秀!