2011-12-03 9 views
7

GCDのドキュメントでは、メインキューに作業を送信するには、NSApplication(またはUIApplication)内で作業するか、またはdispatch_main()を呼び出してソートの実行ループ。しかし、グローバル並行キューを設定するために何かする必要はありますか?アプリケーションまたはrunloop以外でのGrand Central Dispatchの使用

基本的に私が求めているのは、単純なCプログラムを書くと、dispatch_get_global_queue()に行き、それを動作させる前に特別な設定を行う必要がありますか?

答えて

4

いいえ、追加の設定は必要ありません。しかし、dispatch_main()を呼び出してGCDディスパッチャーを起動する必要があります。
dispatch_main()は返さないので、メイン関数の戻り値に到達できなくなります。 GCD &(http://wiki.freebsd.org/GCDに基づいて)グローバルキュー使用して、最小限のCプログラムの

例:これをコンパイルするには

#include <dispatch/dispatch.h> 
#include <err.h> 
#include <stdio.h> 
#include <stdlib.h> 

int main(int argc, char *argv[]) 
{ 
    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
    dispatch_time_t dispatchTime = dispatch_time(DISPATCH_TIME_NOW, 5LL * NSEC_PER_SEC); 
    dispatch_after(dispatchTime, globalQueue, ^{ 
     printf("Dispatched on global queue\n"); 
     exit(0); 
    }); 
    dispatch_main(); 
    return (0); 
} 

を、使用:

clang -Wall -Werror -fblocks -L/usr/local/lib -I/usr/local/include -o test test.c 
+1

あなたはdispatch_mainコールは必要ありません。たとえば、10秒の睡眠に置き換えた場合、5秒のタイマーが引き続きトリガーされます。 – Stripes

7

あなたが呼び出す必要はありませんディスパッチャを起動するには何もしませんが、メインスレッドを終了することはできません。キューに不完全な作業がある場合は、プログラムが終了します。あなたは、セマフォを使用してから出るのメインスレッドを防ぐことができます。

int main() { 
    __block int count = 10; 
    dispatch_semaphore_t done = dispatch_semaphore_create(0); 
    dispatch_time_t naptime; 

    // timeout after 5 seconds 
    naptime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)5E9); 
    // no timeout 
    //naptime = dispatch_time(DISPATCH_TIME_FOREVER, 0); 

    // schedule some work 
    dispatch_async(
     dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), 
     ^{ 
      dispatch_apply(count, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW,0), 
       ^(size_t i){ 
        //... 
        // note: potential race condition on count. 
        // Synchronization left as an exercise. 
        if (--count == 0) { 
         dispatch_semaphore_signal(done); 
        } 
       } 
      ); 
     } 
    ); 

    if (dispatch_semaphore_wait(done, naptime)) { 
     // processing didn't complete in allotted time 
     //... 
    } 
dispatch_release(done); 
    return 0; 
} 

代わりのセマフォ、睡眠を呼び出し、またはループ内の膨大な数に数えるの概念的簡単にあまり使用可能なアプローチは、(コンパイラはdoesnのを確認してあります最適化しない)、または変数(最初はfalseに設定され、処理が完了するとtrueに設定される)がtrueになるまでループします(busy-wait)。これらのそれぞれには重大な欠陥があり、セマフォよりもはるかにあまり好ましくありません。

また、シリアルキューを作成し、それに数回ディスパッチ_同期を呼び出してからディスパッチ_同期を実行し、プログラムを終了することでテストすることもできます。

dispatch_mainを呼び出すか、実行ループを開始する理由はありますが、メインキュー以外のすべてのキューに送信するものは、から開始することができます。 runloop to dispatch_mainが開始されます。

+0

これは、「libdispatchをベースにしたプログラムを正常に終了するにはどうすればいいですか?後で参照できるようになっています。 – Eonil

+1

これは「キュージョブ」の手動カウントが必要です。すべてのキューが排水され、dispatch_sourceが割り当てられていない場合、dispatch_main()を終了する方法はありますか? NSRunLoopに似ています(実行するものが残っていなければ、AFAIKはただ終了します)。 – hnh

+1

いいえ、私が考えることができる最も近いのは、すべてのdispatch_group_asyncを使用して作業を開始してから、exitをトリガーするためにdispatch_group_notifyを使用していますが、それは一般的でも自動でもありません。 deallocハンドラをキューに追加して解放するという作業をすべて開始したかもしれませんが、それには不法な復活の問題があります。私はあなたのアプリが本質的に完全性を認識する方法を知っている必要があると思う、ディスパッチは、そのメッセージを伝播することができますが、それを発信することはできません。 – Stripes

関連する問題