我正在编写一个简单的应用程序,该应用程序应该能够使用Apple的CoreFoundation框架在后台线程中接收和处理通知。这是我要完成的工作:
static void DummyCallback(CFNotificationCenterRef center,
void *observer,
CFStringRef name,
const void *object,
CFDictionaryRef userInfo) {
printf("RECEIVED NOTIFICATION\n");
}
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: sleep\n");
sleep(10);
printf("main: done sleeping\n");
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对象将通知发送到正确的线程的运行循环。
关于multithreading - CoreFoundation : Receive/process notifications in background thread,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6589337/