CFRunLoopRun()vs [NSRunLoop运行]

时间:2011-12-21 13:26:09

标签: macos foundation core-foundation nsrunloop cfrunloop

我有一个NSRunLoop对象,我附加了定时器和流。它很棒。停止它是另一个故事。

我使用[runLoop run]运行循环。

如果我尝试使用CRunLoopStop([[NSRunLoop currentRunLoop] getCFRunLoop])停止循环,循环将不会停止。如果我使用CRunLoopRun()开始循环,它会起作用。我还确保调用是在正确的线程(运行我的自定义运行循环的线程)上进行的。我用pthread_self()调试了这个。

我找到了一个邮件列表存档,开发人员说如果使用CRunLoopStop()的run方法启动循环,则不要使用NSRunLoop。我可以理解为什么它是这样的 - 你通常将初始化器和终结器配对来自同一组函数。

如果没有“诉诸CF”,你如何阻止NSRunLoop?我在stop上看不到NSRunLoop方法。文档说你可以用三种方式停止运行循环:

  1. 配置运行循环以使用超时值
  2. 运行
  3. 告诉运行循环停止使用CFRunLoopStop()
  4. 删除所有输入源,但这是一种不可靠的方法来停止运行循环,因为你永远无法知道什么会阻碍你背后的运行循环。
  5. 好吧,我已经尝试过2.并且有一种“丑陋”的感觉,因为你必须深入研究CF. 3.不可能 - 我不喜欢非确定性代码。

    这给我们留下了1.如果我理解正确的文档,你就不能在已经存在的运行循环中“添加”超时。您只能在超时时运行新的运行循环。如果我运行一个新的运行循环,它将无法解决我的问题,因为它只会创建一个嵌套的运行循环。我仍然会回到原来的那个,同样我想停止......对吧?我可能误解了这个。另外,我不想使用超时值运行循环。如果我这样做,我将不得不在刻录CPU周期(低超时值)和响应性(高超时值)之间进行权衡。

    这是我现在的设置(伪代码ish):

    Communicator.h

    @interface Communicator : NSObject {
        NSThread* commThread;
    }
    
    -(void) start;
    -(void) stop;
    @end
    

    Communicator.m

    @interface Communicator (private)
    -(void) threadLoop:(id) argument;
    -(void) stopThread;
    @end
    
    @implementation Communicator
    -(void) start {
        thread = [[NSThread alloc] initWithTarget:self 
                                         selector:@selector(threadLoop:)
                                           object:nil];
        [thread start];
    }
    
    -(void) stop {
        [self performSelector:@selector(stopThread)
                     onThread:thread
                   withObject:self
                waitUntilDone:NO];
        // Code ommitted for waiting for the thread to exit...
        [thread release];
        thread = nil;
    }
    @end
    
    @implementation Communicator (private)
    -(void) stopThread {
        CRunLoopStop([[NSRunLoop currentRunLoop] getCFRunLoop]);
    }
    
    -(void) threadLoop:(id) argument {
        // Code ommitted for setting up auto release pool
    
        NSRunLoop* runLoop = [NSRunLoop currentRunLoop];
    
        // Code omitted for adding input sources to the run loop
    
        CFRunLoopRun();
        // [runLoop run]; <- not stoppable with 
    
        // Code omitted for draining auto release pools
    
        // Code omitted for signalling that the thread has exited
    }
    @endif
    

    我该怎么办?融入CF是不是常见/好的模式?我不太了解基金会。干扰CF层可能是危险的(关于内存损坏,不一致,内存泄漏)?是否有更好的模式来实现我想要实现的目标?

1 个答案:

答案 0 :(得分:8)

你做得很好。当你无法通过Foundation实现目标时,使用CoreFoundation没有问题。由于CoreFoundation是C,因此更容易搞乱内存管理,但使用CFRunLoop而不是NSRunLoopsometimes it may even be saferCFRunLoop API没有内在的危险性是线程安全的而NSRunLoop不是。)

如果您想停止NSRunLoop,可以使用runMode:beforeDate:运行它。处理输入源后runMode:beforeDate:会立即返回,因此您无需等到达到超时日期。

 NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
 NSDate *date = [NSDate distantFuture];
 while ( !runLoopIsStopped && [runLoop runMode:NSDefaultRunLoopMode beforeDate:date] );

然后,要停止运行循环,您只需将runLoopIsStopped设置为YES