2011-07-18 34 views
27

tôi gặp sự cố khi tạm ngưng truy vấn gcd. Dưới đây là một số mã đó chứng tỏ vấn đề:Tạm dừng sự cố truy vấn GCD

static dispatch_queue_t q=nil; 

static void test(int a){ 
    if(q){ 
     dispatch_suspend(q); 
     dispatch_release(q); 
     q=nil; 
    } 
    q=dispatch_get_global_queue(0,0); 
    dispatch_async(q,^ { 
     while(1){NSLog(@"query %d",a);sleep(2);} 
    }); 

} 

int main(int argc, const char* argv[]){ 
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    test(1); 

    //blah blah blah 

    test(2); 

    while(1){} 
    [pool release]; 
    return 0; 
} 

Những gì tôi đang cố gắng để làm là đình chỉ, phát hành và reinitialise truy vấn q khi kiểm tra hàm được gọi lần thứ hai, nhưng apparenty mã của tôi là sai và cả hai trường hợp truy vấn q tiếp tục chạy.

Trợ giúp của bạn được đánh giá cao, cảm ơn bạn.

+0

Bạn có thể muốn [sử dụng 'NSOperationQueue' thay thế] (http://stackoverflow.com/a/32807804/199360). – adib

Trả lời

39

Bất kỳ khối nào đã được gửi đến hàng đợi của bạn không đồng bộ trước khi bạn thực sự gọi dispatch_suspend() sẽ chạy trước khi tạm dừng có hiệu lực. Trong mã của bạn, bạn đang bắn ra một loạt các khối không đồng bộ, vì vậy một số có thể vẫn còn trong hàng đợi khi bạn gọi kiểm tra (2), và các khối đó sẽ được thực hiện.

Nếu bạn muốn có thể hủy công việc đang chạy của mình, bạn sẽ cần làm như vậy trong logic của riêng bạn. GCD cố tình không phơi bày một API hủy đúng sự thật. Bạn có thể làm một cái gì đó như thế này:

@interface Canceller 
{ 
    BOOL _shouldCancel; 
} 
- (void)setShouldCancel:(BOOL)shouldCancel; 
- (BOOL)shouldCancel; 
@end 

@implementation Canceller 
- (void)setShouldCancel:(BOOL)shouldCancel { 
    _shouldCancel = shouldCancel; 
} 
- (BOOL)shouldCancel { 
    return _shouldCancel; 
} 
@end 

static void test(int a){ 
    static Canceller * canceller = nil; 

    if(q){ 
     [canceller setShouldCancel:YES]; 
     [canceller release]; 
     dispatch_suspend(q); 
     dispatch_release(q); 
     q=nil; 
    } 
    canceller = [[Canceller alloc] init]; 
    q=dispatch_get_global_queue(0,0); 
    dispatch_async(q,^ { 
     while(![canceller shouldCancel]){NSLog(@"query %d",a);sleep(2);} 
    }); 

} 

Bằng cách này, mỗi khối sẽ giữ một tham chiếu đến một đối tượng biết nếu nó nên ngừng làm việc.

+0

Điều này thực hiện thủ thuật, nhờ –

+0

Mã này có nên dừng 'test (1)' khi 'test (2)' được chạy không? Bởi vì nó không dừng lại. –

+0

Nó sẽ sụp đổ trên os mới nhất. Phát hành một đối tượng bị đình chỉ –

5

Từ Apple GCD Reference:

dispatch_suspend

By đình chỉ một đối tượng văn, ứng dụng của bạn có thể tạm thời ngăn chặn việc thực hiện bất kỳ khối kết hợp với đối tượng đó. Việc tạm ngưng xảy ra sau khi hoàn thành bất kỳ khối nào đang chạy tại thời điểm cuộc gọi. Việc gọi hàm này sẽ tăng số đếm tạm dừng của đối tượng và gọi dispatch_resume sẽ giảm số lượng đó. Trong khi số đếm lớn hơn 0, đối tượng vẫn bị treo, vì vậy bạn phải cân bằng mỗi cuộc gọi dispatch_suspend với lệnh dispatch_resume phù hợp.

[đậm tôi]

tôi cho rằng đây là như vậy bởi vì khi một khối được thực thi, nó rời khỏi hàng đợi. Vì vậy, có vẻ như bạn không thể đình chỉ một khối đã được thực hiện.

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