2011-12-03 23 views
7

Trong tài liệu GCD, rõ ràng là phải gửi công việc đến hàng đợi chính, bạn cần phải làm việc trong NSApplication (hoặc UIApplication) hoặc gọi dispatch_main() để hoạt động một vòng lặp chạy của các loại. Tuy nhiên, tôi có cần phải làm bất cứ điều gì để thiết lập hàng đợi đồng thời toàn cầu không?Sử dụng Grand Central Dispatch bên ngoài ứng dụng hoặc runloop

Về cơ bản những gì tôi hỏi là: Nếu tôi viết một chương trình C đơn giản đơn giản, tôi có cần thực hiện bất kỳ thiết lập đặc biệt nào trước khi tôi đi dispatch_get_global_queue() và bắt đầu cho nó hoạt động không?

Trả lời

4

Không, bạn không cần bất kỳ thiết lập bổ sung nào. Nhưng bạn cần gọi dispatch_main() để khởi động trình điều phối GCD.
Khi dispatch_main() không bao giờ trả về, điều này cũng sẽ ngăn không cho chức năng chính của bạn đạt được lợi tức của nó.

Ví dụ cho một chương trình C tối thiểu sử dụng GCD & một hàng đợi toàn cầu (dựa trên 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); 
} 

Để biên dịch này, sử dụng:

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

Bạn không cần cuộc gọi dispatch_main. Nếu bạn thay thế nó bằng giấc ngủ 10 giây, ví dụ như bộ đếm thời gian 5 giây sẽ vẫn kích hoạt. – Stripes

7

Bạn không cần phải gọi bất cứ điều gì để bắt đầu điều phối, nhưng bạn không thể thoát khỏi chủ đề chính hoặc chương trình của bạn sẽ thoát nếu nếu không có công việc không hoàn thành trên hàng đợi. Bạn có thể ngăn các chủ đề chính từ thoát bằng cách sử dụng Cột:

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

Thay vì Cột, có cách tiếp cận khái niệm dễ dàng hơn nhưng ít sử dụng được gọi giấc ngủ, hoặc đếm đến một con số khổng lồ trong một vòng lặp (chắc chắn rằng trình biên dịch doesn không tối ưu hóa nó đi), hoặc looping cho đến khi một biến (ban đầu được đặt thành false, được đặt thành true khi xử lý xong) là true (được gọi là busy-wait). Mỗi trong số này có những thiếu sót nghiêm trọng và ít thích hợp hơn so với một semaphore.

Bạn cũng có thể kiểm tra bằng cách tạo hàng đợi nối tiếp và gọi dispatch_async trên đó một vài lần, sau đó dispatch_sync, sau đó thoát khỏi chương trình.

Có lý do chính đáng để gọi dispatch_main hoặc bắt đầu chạy vòng lặp, nhưng lưu ý những thứ bạn gửi tới hàng đợi bất kỳ, trừ hàng đợi chính có thể bắt đầu TRƯỚC KHI runloop to dispatch_main được bắt đầu.

+0

Đây cũng là câu trả lời hay cho câu hỏi "Cách thoát khỏi chương trình dựa trên' libdispatch' một cách duyên dáng. " Cần chú ý để tham khảo sau này. – Eonil

+1

Điều này đòi hỏi phải đếm thủ công 'công việc xếp hàng'. Có cách nào để kết thúc dispatch_main() khi tất cả các hàng đợi được rút ra/và không có gán dispatch_source? Tương tự như NSRunLoop (mà AFAIK chỉ thoát ra nếu không còn gì để chạy). – hnh

+1

Không, gần nhất tôi có thể nghĩ đến là sử dụng tất cả dispatch_group_async để bắt đầu công việc và sau đó sử dụng dispatch_group_notify để kích hoạt thoát, nhưng đó không phải là chung cũng không tự động. Có lẽ một cái gì đó với bắt đầu tất cả các công việc thêm dealloc xử lý hàng đợi và phát hành chúng, nhưng đó có vấn đề phục sinh bất hợp pháp. Tôi nghĩ rằng ứng dụng của bạn cần vốn đã biết cách nhận biết đầy đủ, công văn có thể giúp truyền bá thông điệp đó nhưng nó không thể bắt nguồn từ nó. – Stripes

Các vấn đề liên quan