在应用程序或运行循环之外使用 Grand Central Dispatch

问题描述 投票:0回答:2

在 GCD 文档中很清楚,要将工作提交到主队列,您需要在

NSApplication
(或
UIApplication
)内工作,或者调用
dispatch_main()
充当某种运行循环。但是,我需要做什么来设置全局并发队列吗?

基本上我要问的是:如果我编写一个简单的 C 程序,在我开始

dispatch_get_global_queue()
并开始让它工作之前,我是否需要执行任何特殊设置?

objective-c ios macos cocoa grand-central-dispatch
2个回答
9
投票

你不需要调用任何东西来启动调度程序,但是你不能退出主线程,否则即使队列上有未完成的工作,你的程序也会退出。您可以使用信号量来阻止主线程退出:

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;
}

代替信号量,有一种概念上更简单但不太实用的方法,即调用 sleep,或者在循环中计数到一个巨大的数字(确保编译器不会优化它),或者循环直到一个变量(最初设置为 false,当处理完成时设置为 true)为 true(称为 busy-wait)。其中每一个都有严重的缺陷,并且远不如信号量更好。

您还可以通过创建一个串行队列并对其调用几次dispatch_async,然后调用dispatch_sync,然后退出程序来测试它。

有充分的理由调用dispatch_main或启动运行循环,但请注意发送到除主队列之外的任何队列的内容可以启动在dispatch_main的运行循环启动之前


6
投票
不,您不需要任何额外的设置。但你需要调用dispatch_main()来启动GCD调度程序。

由于dispatch_main()永远不会返回,这也会阻止你的main函数到达它的返回值。

使用 GCD 和全局队列的最小 C 程序示例(基于

http://wiki.freebsd.org/GCD):

#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
    
© www.soinside.com 2019 - 2024. All rights reserved.