3

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

問題は、ソース/オブザーバー/タイマーがないため、バックグラウンド スレッドの実行ループがすぐに終了することです (リターン コード kCFRunLoopRunTimedOut の代わりに kCFRunLoopRunFinished)。CFNotificationCenterAddObserver は、メイン スレッドの実行ループのみに登録されますが、バックグラウンド スレッドの実行ループには登録されません。

他のもののためにメインスレッドが必要ですが、それを使用して実行ループを実行することはできません。これを機能させる方法はありますか?バックグラウンド スレッドの実行ループに CFNotificationCenter を登録することでしょうか。

前もって感謝します!

4

1 に答える 1

1

http://developer.apple.com/library/mac/#documentation/CoreFoundation/Reference/CFNotificationCenterRef/Reference/reference.htmlに記載されているとおり

オブザーバーが分散通知センターに初めて登録されると、通知センターはシステム全体の通知サーバーとの接続を作成し、リッスン ポートを現在のスレッドの実行ループの共通モードに配置します。通知が配信されると、通知を受信して​​いるオブザーバーが別のスレッドで通知用に登録されていても、通知はこの初期スレッドで処理されます。

ロードされたフレームワークは、コードが実行される前にスレッドを生成し、独自のオブザーバーを追加する可能性があるため、どのスレッドが分散通知を受け取るかを確実に知ることはできません。どのスレッドが通知を処理するかを制御する必要がある場合、コールバック関数は通知を適切なスレッドに転送できる必要があります。CFMessagePort オブジェクトまたはカスタム CFRunLoopSource オブジェクトを使用して、正しいスレッドの実行ループに通知を送信できます。

于 2011-07-06T19:17:57.157 に答える