使用runloop阻塞線程的正確寫法
http://marshal.easymorse.com/archives/4700
runloop可以阻塞線程,等待其他線程執行後再執行。
比如:
@implementation ViewController{
BOOL end;
}
…
– (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@”start new thread …”);
[NSThread detachNewThreadSelector:@selector(runOnNewThread) toTarget:self withObject:nil];
while (!end) {
NSLog(@”runloop…”);
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
NSLog(@”runloop end.”);
}
NSLog(@”ok.”);
}
-(void)runOnNewThread{
NSLog(@”run for new thread …”);
sleep(1);
end=YES;
NSLog(@”end.”);
}
但是這樣做,運行時會發現,while循環後執行的語句會在很長時間後才被執行。
那是不是可以這樣:
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
縮短runloop的休眠時間,看起來解決了上面出現的問題。
不過這樣也又問題,runloop對象被經常性的喚醒,這違背了runloop的設計初衷。runloop的作用就是要減少cpu做無謂的空轉,cpu可在空閒的時候休眠,以節約電量。
那麼怎麼做呢?正確的寫法是:
-(void)runOnNewThread{NSLog(@”run for new thread …”);
sleep(1);
[self performSelectorOnMainThread:@selector(setEnd) withObject:nil waitUntilDone:NO];
NSLog(@”end.”);
}
-(void)setEnd{
end=YES;
}
見黑體斜體字部分,要將直接設置變量,改爲向主線程發送消息,執行方法。問題得到解決。
這裏要說一下,造成while循環後語句延緩執行的原因是,runloop未被喚醒。因爲,改變變量的值,runloop對象根本不知道。延緩的時長總是不定的,這是因爲,有其他事件在某個時點喚醒了主線程,這才結束了while循環。那麼,向主線程發送消息,將喚醒runloop,因此問題就解決了。