CFRunLoopRun()与[NSRunLoop运行] [英] CFRunLoopRun() vs [NSRunLoop run]

查看:397
本文介绍了CFRunLoopRun()与[NSRunLoop运行]的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个NSRunLoop对象,向其附加了计时器和流.效果很好.完全停止是另一个故事.

I have an NSRunLoop object, to which I attach timers and streams. It works great. Stopping it is another story alltogether.

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

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

If I try to stop the loop using CRunLoopStop([[NSRunLoop currentRunLoop] getCFRunLoop]), the loop won't stop. If I start the loop using CRunLoopRun() instead, it works. I have also made sure that the call is made on the correct thread (the one running my custom run loop). I have debugged this with pthread_self().

我找到了一个邮件列表档案,开发人员说如果您使用NSRunLoop的run方法启动循环,请不要使用CRunLoopStop()".我能理解为什么会这样-通常您会从同一组函数中将初始化器和终结器配对.

I found a mailing list archive, where a developer said "don't bother using CRunLoopStop() if you started the loop using the run method of NSRunLoop". I can understand why it is the way it is - you normally pair up initializers and finalizers from the same set of functions.

如何在不重新分类为CF"的情况下停止NSRunLoop?我没有在NSRunLoop上看到stop方法.文档说您可以通过三种方式停止运行循环:

How do you stop an NSRunLoop without "resorting to CF"? I don't see a stop method on NSRunLoop. The docs says that you can stop a run loop in three ways:

  1. 配置运行循环以超时值运行
  2. 告诉运行循环停止使用CFRunLoopStop()
  3. 删除所有输入源,但这是停止运行循环的一种不可靠的方法,因为您永远不知道是什么使运行循环滞后于背后

好吧,我已经尝试过2.感觉有点丑陋",因为您必须深入研究CF. 3.不可能-我不喜欢非确定性代码.

Well, I already tried 2. and there's an "ugly" feel to it, because you have to dig into CF. 3. is out of the question - I don't fancy non deterministic code.

这给我们留下1.如果我正确地理解了文档,则无法将超时添加"到一个已经存在的运行循环中.您只能在超时的情况下运行新的运行循环.如果我运行一个新的运行循环,它将无法解决我的问题,因为它只会创建一个嵌套的运行循环.我仍然会跳回旧的,就像我想停下来一样...对吗?我可能误会了这一点.另外,我不想使用超时值运行循环.如果这样做,我将不得不在燃烧的CPU周期(低超时值)和响应能力(高超时值)之间进行权衡.

This leaves us with 1. If I understand the docs correctly, you cannot "add" a timeout to an already existing run loop. You can only run new run loops with a timeout. If I run a new run loop, it will not solve my problem, as it will only create a nested run loop. I'll still pop right back into the old one, the same I wanted to stop... right? I might have misunderstood this one. Also, I don't want to run the loop with a timeout value. If I do, I'll have to make a trade off between burning CPU cycles (low timeout value) and responsiveness (high timeout value).

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

This is the setup I have right now (pseudo code-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层是否可能很危险(就内存损坏,不一致,内存泄漏而言)?有没有更好的模式可以实现我想要实现的目标?

What am I to do? Is it common/a good pattern to mess around with CF? I don't know Foundation well enough. Is interfering in the CF layer possibly dangerous (with respect to memory corruption, inconsistencies, memory leaks)? Is there a better pattern to achieve what I am trying to achieve?

推荐答案

您做得很好.当您无法通过Foundation实现目标时,使用CoreFoundation没问题.由于CoreFoundation是C,因此更容易弄乱内存管理,但是使用CFRunLoop而不是NSRunLoop并没有内在的危险(

You're doing well. There's not problem to use CoreFoundation when you cannot achieve your goal with Foundation. As CoreFoundation is C, it's easier to mess up with memory management but there is no intrinsic danger in using CFRunLoop rather than NSRunLoop (sometimes it may even be safer: CFRunLoop API are thread-safe whereas NSRunLoop isn't).

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

If you want to stop your NSRunLoop, you can run it using runMode:beforeDate:. runMode:beforeDate: returns as soon as an input source is processed so you don't need to wait until the timeout date is reached.

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

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

Then, to stop the run loop, you just need to set runLoopIsStopped to YES.

这篇关于CFRunLoopRun()与[NSRunLoop运行]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆