我试图理解 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
}
在上面的代码中,我正在创建一个后台线程,并在该后台线程上调用 function testMethod
。在里面testmethod
我正在运行一段时间,它检查 BOOL 变量 exitThread
并使用 NSRunLoop 的方法运行后台线程的- (BOOL)runMode: beforeDate:
RunLoop。有两个 IBAction 连接到两个按钮。正如 IBActions 的名称所暗示的,其中一个是 to exitThread
,另一个是唤醒线程并执行在 while 循环中编写的 NSLog 语句。
上面的代码按照我的预期运行。每当doDomeWorkOnBackgroundThread
执行方法时,线程从其运行循环中唤醒,执行 while 循环的下一次迭代,检查 BOOL 变量exitThread
并找到它的值,因为 false 进入 while 循环并执行 NSlog 语句。类似地,当exitThread:
方法执行时,exitThread
变量设置为 true,这会导致 while 循环和线程退出。
但是,我需要更多说明:
1)如果不是runMode: beforeDate:
在while循环中使用,而是使用NSRunLoop的run
orrunUntilDate:
方法,那么在exitThread:
执行方法时线程永远不会退出。在后台线程上调用 exitBackgroundThread 方法,但 while 循环永远不会执行它的下一次迭代(就像我使用 时那样runMode: beforeDate:
),因此线程永远不会退出。
2)我尝试将exitBackgroundThread
方法更改为
- (void)exitBackgroundThread {
exitThread = YES;
CFRunLoopStop(CFRunLoopGetCurrent());
}
由于exitBackgroundThread
在后台线程上执行 CFRunLoopGetCurrent() 应该给出后台线程的 RunLoop。因此,无论我使用哪种 NSRunLoop 方法来启动 RunLoop,理想情况下都应该停止后台线程的运行循环。所以无论如何线程必须在调用上述函数时退出。但它只是没有发生。
我知道我在这里遗漏了一些东西,我正在做大量的谷歌搜索以找到这个问题的答案,但似乎无法找到正确的答案。
**编辑
我发现这个问题与我的第一个查询非常相似。它在很大程度上消除了我的第一个疑问。