如何正确结束驱动RunLoop的NSThread

来源:互联网 发布:剑三曹雪阳捏脸数据 编辑:程序博客网 时间:2024/05/02 01:08

不负责任的apple sample

Apple的Sample说可以轮循线程是否应该退出,但是有bug

see:documentation/Cocoa/Conceptual/Multithreading/CreatingThreads/CreatingThreads.html

- (void)threadRuntime:(id)arg{    @autoreleasepool {        GXLog(@"Thread created............>>>>>>>>>>>>>>>>>>>>>>");        NSRunLoop *rl = [NSRunLoop currentRunLoop];                [_target performSelector:_selector withObject:arg];        [_target release];        _target = nil;                BOOL exitNow = NO;        NSMutableDictionary *threadDict = [[NSThread currentThread] threadDictionary];        [threadDict setValue:[NSNumber numberWithBool:exitNow] forKey:@"ThreadShouldExitNow"];                NSDate *date = [NSDate date];        while (!exitNow) {            [rl runUntilDate:date];            exitNow = [[threadDict valueForKey:@"ThreadShouldExitNow"] boolValue];        }        [_thread release];        _thread = nil;                GXLog(@"Thread Exited............<<<<<<<<<<<<<<<<<<<<<<");    }}

Instruments进行Time Profile是这样的:


做的题外的修改,如果这样轮询

        while (!exitNow) {            [rl runUntilDate:[NSDate date]];            exitNow = [[threadDict valueForKey:@"ThreadShouldExitNow"] boolValue];        }

内存占用很恐怖

[NSDate date] autorelease来不及释放,程序最终会因为内存耗尽被系统干掉。


使用CFRunLoopRun/CFRunLoopStop正确结束NSThread

一切皆因轮询而起,那就破了轮询

- (void)threadRuntime:(id)arg{    @autoreleasepool {        GXLog(@"Thread created............>>>>>>>>>>>>>>>>>>>>>>");        [_target performSelector:_selector withObject:arg];        [_target release];        _target = nil;                CFRunLoopRun();                        [_thread release];        _thread = nil;                GXLog(@"Thread Exited............<<<<<<<<<<<<<<<<<<<<<<");    }}- (void)stop{    if (!_thread) {        return;    }        CFRunLoopStop(CFRunLoopGetCurrent());}

千万小心,stop会直接停止当前线程得RunLoop,这要求在RunLoop所在的线程执行stop, 实际情况可能在其它线程调用stop。


小结

虽然cocoa&xcode有很多利器,但是能不用多线程还是别用吧。



原创粉丝点击