我有一个NSRunLoop对象,我附加了定时器和流。它很棒。停止它是另一个故事。
我使用[runLoop run]
运行循环。
如果我尝试使用CRunLoopStop([[NSRunLoop currentRunLoop] getCFRunLoop])
停止循环,循环将不会停止。如果我使用CRunLoopRun()
开始循环,它会起作用。我还确保调用是在正确的线程(运行我的自定义运行循环的线程)上进行的。我用pthread_self()
调试了这个。
我找到了一个邮件列表存档,开发人员说如果使用CRunLoopStop()
的run方法启动循环,则不要使用NSRunLoop
。我可以理解为什么它是这样的 - 你通常将初始化器和终结器配对来自同一组函数。
如果没有“诉诸CF”,你如何阻止NSRunLoop
?我在stop
上看不到NSRunLoop
方法。文档说你可以用三种方式停止运行循环:
CFRunLoopStop()
好吧,我已经尝试过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层可能是危险的(关于内存损坏,不一致,内存泄漏)?是否有更好的模式来实现我想要实现的目标?
答案 0 :(得分:8)
你做得很好。当你无法通过Foundation实现目标时,使用CoreFoundation没有问题。由于CoreFoundation是C,因此更容易搞乱内存管理,但使用CFRunLoop
而不是NSRunLoop
(sometimes it may even be safer:CFRunLoop
API没有内在的危险性是线程安全的而NSRunLoop
不是。)
如果您想停止NSRunLoop
,可以使用runMode:beforeDate:
运行它。处理输入源后runMode:beforeDate:
会立即返回,因此您无需等到达到超时日期。
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
NSDate *date = [NSDate distantFuture];
while ( !runLoopIsStopped && [runLoop runMode:NSDefaultRunLoopMode beforeDate:date] );
然后,要停止运行循环,您只需将runLoopIsStopped
设置为YES
。