首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >performSelector:onThread中断runloop?

performSelector:onThread中断runloop?
EN

Stack Overflow用户
提问于 2013-06-07 15:57:28
回答 2查看 1.5K关注 0票数 0

我不知道如何使用performSelector:onThread接口,这里我需要一些建议。

据我所知,我需要一个runloop来调用performSelector:onThread,所以我做了一个。但是我发现了一个问题:一旦我调用了performSelector:onThreadrunloop就会停止。

这是我的测试代码,runloop是用function kickOffThread编写的。

代码语言:javascript
复制
- (void)setCurrentThread
{
    self.thread = [NSThread currentThread];
}

- (void)kickOffThread
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    [self performSelector:@selector(setCurrentThread) withObject:nil afterDelay:0];
    while (!threadCheck) {
        NSLog(@"threadCheck = %d", threadCheck);
        [[NSRunLoop currentRunLoop] run];
    }
    [self doSomeCleanUp];
    NSLog(@"thread exit ....");
    [pool release];
}

我通过performInBackground调用kickOffThread

代码语言:javascript
复制
   [self performSelectorInBackground:@selector(kickOffThread) withObject:nil];

在mainThread中,我调用下面的接口将threadCheck设置为YES,它被正确调用,但我的线程循环突然停止。

代码语言:javascript
复制
[self performSelector:@selector(signalThreadCheck) onThread:self.thread withObject:nil waitUntilDone:NO];
-(void)signalThreadCheck
{
    NSLog(@" signalThreadCheck ... ");
    threadCheck = YES;
}

终端日志结果如下:“线程退出...”未打印。有人告诉我问题出在哪里吗?

代码语言:javascript
复制
2013-06-07 15:51:54.827 MBSMapSample[23582:17403] threadCheck = 0
2013-06-07 15:51:54.827 MBSMapSample[23582:17403] threadCheck = 0
2013-06-07 15:51:54.827 MBSMapSample[23582:17403] threadCheck = 0
2013-06-07 15:51:54.836 MBSMapSample[23582:17403] threadCheck = 0
2013-06-07 15:51:54.837 MBSMapSample[23582:17403] threadCheck = 0
2013-06-07 15:51:54.837 MBSMapSample[23582:17403] threadCheck = 0
2013-06-07 15:51:54.837 MBSMapSample[23582:17403] threadCheck = 0
2013-06-07 15:51:54.837 MBSMapSample[23582:17403] threadCheck = 0
2013-06-07 15:51:54.837 MBSMapSample[23582:17403] threadCheck = 0
2013-06-07 15:51:54.840 MBSMapSample[23582:17403] threadCheck = 0
2013-06-07 15:51:54.844 MBSMapSample[23582:17403] threadCheck = 0
2013-06-07 15:51:54.846 MBSMapSample[23582:17403]  signalThreadCheck ... 
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-06-07 17:23:37

这条线没有断。它只是隐藏在mach_msg_trap中

如果没有输入源或计时器附加到run循环,此方法将立即退出;否则,它将在NSDefaultRunLoopMode中运行接收器

onThread使调用者向目标线程添加一个输入源。因此,NSRunLoop运行方法实际上将调用NSRunLoop(NSRunLoop) runMode: beforeDate :并将无限日期作为beforeDate参数发送。

如果要停止线程,请使用NSRunLoop(NSRunLoop) runMode:beforeDate:,并发送一个有限的日期,如下所示:

代码语言:javascript
复制
BOOL shouldKeepRunning = YES;        // global
NSRunLoop *theRL = [NSRunLoop currentRunLoop];
while (shouldKeepRunning && 
    [theRL runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]);
票数 0
EN

Stack Overflow用户

发布于 2013-06-07 18:08:11

准确地知道您试图在这里完成什么将会有所帮助,因为元问题是NSThread是否是完成此任务的正确工具。GCD通常是首选的。

尽管如此,要考虑的一件事是NSRunLoop是否有输入源。让我们举一个稍微简化的例子,我们分离一个新的NSThread,如下所示:

代码语言:javascript
复制
- (void)viewDidLoad
{
    [super viewDidLoad];

    _threadCheck = NO;  // this is an ivar
    [NSThread detachNewThreadSelector:@selector(kickOffThread) toTarget:self withObject:nil];

    double delayInSeconds = 2.0;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
        for( uint8_t i = 0; i < 10; i++ )
            [self performSelector:@selector(logSomething) onThread:self.thread withObject:nil waitUntilDone:NO];
        [self performSelector:@selector(signalThreadCheck) onThread:self.thread withObject:nil waitUntilDone:NO];
    });

}

- (void)kickOffThread
{
    _thread = [NSThread currentThread];  // this is an ivar
    NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
    while( !_threadCheck && [runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]] );
    [self doSomeCleanUp];
    printf("thread exit...\n");
}

- (void)doSomeCleanUp {
    printf("cleaning up...\n");
}

- (void)logSomething {
    printf("in background thread...\n");
}

-(void)signalThreadCheck
{
    printf("signalThreadCheck\n");
    _threadCheck = YES;
}

在控制台上,我得到:

代码语言:javascript
复制
cleaning up...
thread exit...

为什么从来没有给logSomething打过电话?因为我们产生的后台线程的run循环没有输入源,所以它会立即退出。例如,如果我们使用[NSPort port]添加一个输入源,我们可以保持生成的线程的运行循环旋转,例如:

代码语言:javascript
复制
- (void)kickOffThread
{
    _thread = [NSThread currentThread];
    NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
    [runLoop addPort:[NSPort port] forMode:NSRunLoopCommonModes];
    while( !_threadCheck && [runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]] );
    [self doSomeCleanUp];
    printf("thread exit...\n");
}

现在,我们将以下内容输出到控制台:

代码语言:javascript
复制
in background thread...
in background thread...
in background thread...
in background thread...
in background thread...
in background thread...
in background thread...
in background thread...
in background thread...
in background thread...
signalThreadCheck
cleaning up...
thread exit...

More about run loops和来自documentation

如果没有输入源或计时器附加到run循环,则此方法run立即退出;否则,它通过重复调用NSDefaultRunLoopMode :beforeDate:在runMode中运行接收器。换句话说,这个方法有效地开始了一个无限循环,处理来自运行循环的输入源和定时器的数据。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16979020

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档