NSRunLoop-需要澄清 [英] NSRunLoop- Clarification needed

查看:151
本文介绍了NSRunLoop-需要澄清的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图理解RunLoops的概念.我已经阅读了有关RunLoops的Apple开发人员指南,并且在某种程度上我了解了RunLoops的概念.为了使我的概念更清晰,我编写了一个非常简单的代码,其中使用了RunLoops.该代码可以在下面看到.

I am trying to understand the concept of RunLoops. I have read Apple developer's guide on RunLoops and to some extent I have understood the concept of RunLoops. To make my concept more clearer I wrote a very simple code which uses RunLoops in it. The code can be seen below.

    - (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,并使用NSRunLoop的- (BOOL)runMode: beforeDate:方法运行后台线程的RunLoop. 有两个附加在两个按钮上的IBAction.正如IBAction的名称所暗示的那样,其中之一是exitThread,另一种是唤醒线程并执行在while循环中编写的NSLog语句.

In above code I am creating a background thread and on that background thread I am calling function testMethod . Inside testmethod I am running a while which checks for BOOL variable exitThread and runs the background thread's RunLoop using the - (BOOL)runMode: beforeDate: method of NSRunLoop. There are two IBActions which are attached to two buttons. As the name of the IBActions suggest one of them is to exitThread and other one is to wake up the thread and execute NSLog statement written in the while loop.

上面的代码按照我的预期运行.每当执行doDomeWorkOnBackgroundThread方法时,线程都会从其运行循环中唤醒,执行while循环的下一次迭代,检查BOOL变量exitThread并在while循环内查找为false的值时执行NSlog语句. 同样,当执行exitThread:方法时,将exitThread变量设置为true,这会导致while循环和线程退出.

The above code runs just as I expected. Whenever doDomeWorkOnBackgroundThread method is executed thread wakes up from its runloop,performs the next iteration of the while loop, check for BOOL variable exitThread and on finding it value as false goes inside the while loop and executes the NSlog statement. Similarly When exitThread: method is executed the exitThread variable is set to true which causes the while loop and the thread to exit.

但是我需要更多说明:

1)如果不是在while循环中使用runMode: beforeDate:,而是使用NSRunLoop的runrunUntilDate:方法,那么执行exitThread:方法时永远不会退出线程.在后台线程上调用exitBackgroundThread方法,但是while循环永远不会执行它的下一次迭代(就像我使用runMode: beforeDate:时所做的那样),因此线程永远不会退出.

1) If instead of using runMode: beforeDate: in the while loop , I use run or runUntilDate: method of NSRunLoop, then the thread is never exited when exitThread: method is executed. The exitBackgroundThread method is called on the background thread but the while loop never performs it's next iteration(as it does when I use runMode: beforeDate:) and hence the thread is never exited.

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

2) I tried changing exitBackgroundThread method to

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

由于exitBackgroundThread是在后台线程上执行的,因此CFRunLoopGetCurrent()应该提供后台线程的RunLoop.因此,理想情况下,无论我使用哪种NSRunLoop方法启动RunLoop,这都应该停止后台线程的运行循环.因此,无论如何,线程必须在调用上述函数时退出.但这只是没有发生.

Since exitBackgroundThread is executed on background thread CFRunLoopGetCurrent() should give the RunLoop of background thread. So this should ideally stop the run loop of the background thread regardless of whatever method of NSRunLoop I am using to start the RunLoop. So in any case thread must exit on call of above function. But it is just not happening.

我知道我在这里遗漏了一些东西,我正在做大量的谷歌搜索工作来找到该问题的答案,但似乎找不到正确的答案.

I know I am missing something here and I am doing a fair amount of googling on my part to find answer to this question but just cant seem to find the right answer.

**编辑

我发现了这个问题,该问题与我的第一个查询非常相似.这在很大程度上消除了我的第一个疑问.

I have found this question which is very similar to my first query. It clears my first doubt to much extent.

推荐答案

  1. 使用runrunUntilDate:而不是runMode:beforeDate:时看到的更改是预期的. runMode:beforeDate:的文档说:

  1. The change you see when you use run or runUntilDate: instead of runMode:beforeDate: is expected. The documentation for runMode:beforeDate: says this:

它在处理第一个输入源或达到limitDate之后返回.

有一个输入源负责处理performSelector:...请求.因此,当您发送performSelector:...时,运行循环将处理输入源,然后返回.

There is an input source responsible for handling the performSelector:... requests. So when you send performSelector:..., the run loop processes an input source and then returns.

另一方面,run的文档说:

它通过反复调用runMode:beforeDate:在NSDefaultRunLoopMode中运行接收器.换句话说,此方法有效地开始了一个无限循环,该循环处理来自运行循环的输入源和计时器的数据.

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.

So after the run loop processes the input source for your performSelector:... request, it waits for another input source to be ready. It doesn't return. Since it doesn't return, your while loop never gets a chance to test exitThread.

您尝试使用CFRunLoopStop是个好主意,但不幸的是,run的文档说:

Your attempt to use CFRunLoopStop is a good idea, but unfortunately, the documentation for run says this:

如果您想终止运行循环,则不应使用此方法.而是使用其他运行方法之一,并循环检查自己的其他任意条件.

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.

So you can't rely on CFRunLoopStop to make run return.

相反,您可以降到更低的级别并使用CFRunLoopRun来运行运行循环,因为记录了CFRunLoopStop可使该函数返回:

Instead, you can drop to a lower level and use CFRunLoopRun to run the run loop, because CFRunLoopStop is documented to make that function return:

此函数强制rl停止运行,并将控制权返回给调用CFRunLoopRunCFRunLoopRunInMode的函数以用于当前的运行循环激活.

This function forces rl to stop running and return control to the function that called CFRunLoopRun or CFRunLoopRunInMode for the current run loop activation.

因此,请尝试运行您的运行循环:

So try this to run your run loop:

while(!exitThread) {
    NSLog(@"Thread did some work");
    CFRunLoopRun([NSRunLoop currentRunLoop].getCFRunLoop);
}

这篇关于NSRunLoop-需要澄清的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆