我不知道如何使用performSelector:onThread接口,这里我需要一些建议。
据我所知,我需要一个runloop来调用performSelector:onThread,所以我做了一个。但是我发现了一个问题:一旦我调用了performSelector:onThread,runloop就会停止。
这是我的测试代码,runloop是用function kickOffThread编写的。
- (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
[self performSelectorInBackground:@selector(kickOffThread) withObject:nil];在mainThread中,我调用下面的接口将threadCheck设置为YES,它被正确调用,但我的线程循环突然停止。
[self performSelector:@selector(signalThreadCheck) onThread:self.thread withObject:nil waitUntilDone:NO];
-(void)signalThreadCheck
{
NSLog(@" signalThreadCheck ... ");
threadCheck = YES;
}终端日志结果如下:“线程退出...”未打印。有人告诉我问题出在哪里吗?
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 ... 发布于 2013-06-07 17:23:37
这条线没有断。它只是隐藏在mach_msg_trap中
如果没有输入源或计时器附加到run循环,此方法将立即退出;否则,它将在NSDefaultRunLoopMode中运行接收器
onThread使调用者向目标线程添加一个输入源。因此,NSRunLoop运行方法实际上将调用NSRunLoop(NSRunLoop) runMode: beforeDate :并将无限日期作为beforeDate参数发送。
如果要停止线程,请使用NSRunLoop(NSRunLoop) runMode:beforeDate:,并发送一个有限的日期,如下所示:
BOOL shouldKeepRunning = YES; // global
NSRunLoop *theRL = [NSRunLoop currentRunLoop];
while (shouldKeepRunning &&
[theRL runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]);发布于 2013-06-07 18:08:11
准确地知道您试图在这里完成什么将会有所帮助,因为元问题是NSThread是否是完成此任务的正确工具。GCD通常是首选的。
尽管如此,要考虑的一件事是NSRunLoop是否有输入源。让我们举一个稍微简化的例子,我们分离一个新的NSThread,如下所示:
- (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;
}在控制台上,我得到:
cleaning up...
thread exit...为什么从来没有给logSomething打过电话?因为我们产生的后台线程的run循环没有输入源,所以它会立即退出。例如,如果我们使用[NSPort port]添加一个输入源,我们可以保持生成的线程的运行循环旋转,例如:
- (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");
}现在,我们将以下内容输出到控制台:
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中运行接收器。换句话说,这个方法有效地开始了一个无限循环,处理来自运行循环的输入源和定时器的数据。
https://stackoverflow.com/questions/16979020
复制相似问题