【问题标题】:CoreFoundation: Receive/process notifications in background threadCoreFoundation:在后台线程中接收/处理通知
【发布时间】:2011-07-05 21:56:58
【问题描述】:

我正在编写一个简单的应用程序,它应该能够使用 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?

提前致谢!

【问题讨论】:

    标签: multithreading macos background notifications runloop


    【解决方案1】:

    http://developer.apple.com/library/mac/#documentation/CoreFoundation/Reference/CFNotificationCenterRef/Reference/reference.html中所述

    第一次向分布式通知中心注册观察者时,通知中心会创建与系统范围通知服务器的连接,并将监听端口放入当前线程运行循环的常用模式中。当通知被传递时,它会在这个初始线程上进行处理,即使接收通知的观察者在不同的线程上注册了通知。

    因为加载的框架可能会在您的代码执行之前生成线程并添加它们自己的观察者,所以您无法确定哪个线程会接收分布式通知。如果您需要控制哪个线程处理通知,您的回调函数必须能够将通知转发到正确的线程。您可以使用 CFMessagePort 对象或自定义 CFRunLoopSource 对象将通知发送到正确线程的运行循环。

    【讨论】:

    • 感谢您的回答。我也读过那段话,但这并不能解决我的问题。为了接收通知,主线程中需要一个 CFRunLoop。应该有办法解决这个问题。
    • 实现你自己的通知中心,它会关心线程的运行循环。
    • 也想过这个问题,但我不知道如何将它连接到 distnoted 守护进程。 Core Foundation 的这一部分似乎是闭源的。而且我不确定该解决方案的未来证明。苹果可能会在某个时候改变一些内部结构
    • 是的。唯一的解决方案可能是实现您自己的“通知调度程序”,它将在主线程中接收分布式通知并将相应的消息发送到专用线程。无论如何都会使用主线程....
    猜你喜欢
    • 2022-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-28
    • 1970-01-01
    • 2021-01-23
    • 2013-01-14
    相关资源
    最近更新 更多