2011-07-18 19 views
27

Bir gcd sorgusunu askıya almada sorun yaşıyorum. İşte sorun gösterir bazı kod şudur:, serbest bırakma ve yeniden başlatmanız sorgu q fonksiyon testi ikinci kez denir ama apparenty benim kod yanlış ve her iki örnek ne ben askıya olduğunu yapmaya çalışıyorumGCD sorgu sorununu askıya alma

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

sorgu q çalışmaya devam ediyor.

Kişisel Yardım çok takdir

, teşekkür ederim. Apple GCD Reference itibaren

+0

[Use 'NSOperationQueue' yerine onun yerine] kullanmak isteyebilirsiniz (http://stackoverflow.com/a/32807804/199360). – adib

cevap

39

Gerçekte dispatch_suspend() işlevini çağırmadan önce sıranıza eşzamansız olarak gönderilen tüm bloklar, askıya alma işlemi yürürlüğe girmeden önce çalıştırılır. Kodunuzda, bir zamanlar blokları eşzamansız olarak kovuyorsunuz, bu nedenle test (2) dediğinizde, bazıları hala kuyruktadır ve bu bloklar çalıştırılacaktır.

Çalışan işlerinizi iptal etmek isterseniz, bunu kendi mantığınızda yapmanız gerekir. GCD, kasıtlı olarak gerçek bir iptal API'sini ortaya çıkarmaz. Her blok o işi durdurmak gerekip gerekmediğini bilen bir nesneye bir başvuru tutacak, bu sayede

@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öyle bir şey yapabilirdi.

+0

Bu hile yok, teşekkürler –

+0

Bu kod 'test (2) 'çalıştırıldığında sınama (1)' i durdurmalı mı? Çünkü onu durdurmuyor. –

+0

En yeni işletim sisteminde çökecektir. Askıya alınmış bir nesnenin serbest bırakılması –

5

: Bir gönderme nesnesi askıya By

dispatch_suspend

, başvurunuz geçici olarak bu nesneyle ilgili herhangi blokların yürütülmesini önleyebilir. Süspansiyon, numaralı çağrı sırasında çalışan tüm blokların tamamlanmasından sonra gerçekleşir. Bu işlevin çağrılması, nesnenin askıya alınma sayısını artırır ve dispatch_resume ifadesini çağırarak onu azaltır. Sayım sıfırdan büyük olsa da, nesne askıda kalır, dolayısıyla her dispatch_suspend çağrısını eşleşen bir dispatch_resume çağrısı ile dengelemeniz gerekir.

[kalın maden]

Bir blok çalıştırıldığında, bu kuyruğu bıraktığı için bu kadar olduğunu varsayalım. Yani, zaten uygulamada bir bloğu askıya alamazsınız.

İlgili konular