2011-07-05 18 views
2

AppleのCoreFoundationフレームワークを使用してバックグラウンドスレッドで通知を受信して​​処理できる単純なアプリケーションを作成しています。ここで私が達成しようとしているものです: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をバックグラウンドスレッドの実行ループに登録することによって?

ありがとうございます!

答えて

1

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

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

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

+0

あなたの答えをありがとう。私はその通路も読んだが、これは私の問題を解決しない。通知を受け取るには、メインスレッドでCFRunLoopが必要です。その周りに道があるはずです。 – Benjamin

+0

スレッドの実行ループを気にする独自の通知センターを実装します。 – Andrew

+0

それについても考えましたが、私はそれをdistnotedデーモンに接続する方法を理解できませんでした。 Core Foundationのこの部分は閉鎖されたソースのようです。そして、その解決策が将来どういうものになるかはわかりません。 Appleはある点で内部の一部を変更するかもしれない – Benjamin

関連する問題