我正在编写一个简单的应用程序,它应该能够使用Apple的CoreFoundation框架在后台线程中接收和处理通知。以下是我想要完成的:
static void DummyCallback(CFNotificationCenterRef center,
void *observer,
CFStringRef name,
const void *object,
CFDictionaryRef userInfo) {
printf("RECEIVED NOTIFICATIONn");
}
void *ThreadStart(void *arg) {
CFNotificationCenterAddObserver(CFNotificationCenterGetDistributedCenter(),
NULL,
&DummyCallback,
NULL,
CFSTR("TEST_OBJECT"),
CFNotificationSuspensionBehaviorDeliverImmediately);
printf("background thread: run run loop (should take 5 sec to exit)n");
int retval = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 5, true);
printf("background thread: exited from run loop (retval: %d)n", retval);
return NULL;
}
int main(int argc, char** argv) {
pthread_t thread;
int rc = pthread_create(&thread, NULL, &ThreadStart, NULL);
assert(rc == 0);
printf("main: sleepn");
sleep(10);
printf("main: done sleepingn");
return 0;
}
如果我运行程序,我只得到
main: sleep
background thread: run run loop (should take 5 sec to exit)
background thread: exited from run loop (retval: 1)
main: done sleeping
问题是后台线程的运行循环立即退出(返回代码kCFRunLoopRunFinished而不是kCFRunLoopRunTimedOut),因为没有源/观察者/计时器。CFNotificationCenterAddObserver只在主线程的运行循环中注册自己,而不是在后台线程中注册自己。
我需要主线程的一些其他的东西,不能用它来运行它的运行循环。有什么办法让它工作吗?也许通过注册CFNotificationCenter与后台线程的运行循环?
提前感谢!
如http://developer.apple.com/library/mac/#documentation/CoreFoundation/Reference/CFNotificationCenterRef/Reference/reference.html
所述第一次向分布式通知中心注册观察者时,通知中心创建与系统范围通知服务器的连接,并将侦听端口放置到当前线程运行循环的公共模式中。当一个通知被传递时,它将在这个初始线程上进行处理,即使接收通知的观察者在另一个线程上注册了该通知。
因为加载的框架可能会在你的代码执行之前产生线程并添加它们自己的观察者,所以你不能确定哪个线程会收到分布式通知。如果需要控制哪个线程处理通知,则回调函数必须能够将通知转发给适当的线程。您可以使用CFMessagePort对象或自定义CFRunLoopSource对象来向正确的线程的运行循环发送通知。