gpt4 book ai didi

objective-c - NSRunLoop- 需要澄清

转载 作者:搜寻专家 更新时间:2023-10-30 19:41:29 25 4
gpt4 key购买 nike

我正在尝试理解 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 的 runrunUntilDate: 方法,那么当执行 exitThread: 方法时,线程永远不会退出。 exitBackgroundThread 方法在后台线程上调用,但 while 循环从不执行它的下一次迭代(就像我使用 runMode: beforeDate: 时那样),因此线程永远不会退出。

2) 我尝试将 exitBackgroundThread 方法更改为

- (void)exitBackgroundThread {
exitThread = YES;
CFRunLoopStop(CFRunLoopGetCurrent());
}

因为 exitBackgroundThread 是在后台线程上执行的,所以 CFRunLoopGetCurrent() 应该给出后台线程的 RunLoop。因此,无论我使用何种 NSRunLoop 方法启动 RunLoop,这应该理想地停止后台线程的运行循环。所以在任何情况下线程都必须在调用上述函数时退出。但这并没有发生。

我知道我在这里遗漏了一些东西,并且我正在做大量的谷歌搜索以找到这个问题的答案,但似乎找不到正确的答案。

**编辑

我找到了 this与我的第一个查询非常相似的问题。它在很大程度上消除了我的第一个疑问。

最佳答案

  1. 您在使用 runrunUntilDate: 而不是 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

  2. 您尝试使用 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 called CFRunLoopRun or CFRunLoopRunInMode 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/

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