2013-03-17 13 views
5

Tworzę program, który może, w zależności od innych rzeczy, włączać i wyłączać muzykę. Problem polega na tym, że inne wątki/kolejki mogą zatrzymać muzykę, co oznacza, że ​​zanikanie i zanikanie muszą również nie tylko zatrzymać się, ale wstrzymać. Muszę być w stanie zatrzymać "timer" na dispatch_after (ponieważ jest to wywoływane, gdy muzyka zaczyna się odtwarzać, aby powiedzieć, kiedy zacząć gasnąć, co musiałoby być opóźnione, gdyby zostało wstrzymane) i wstrzymać kolejkę sam (aby wstrzymać rozjaśniania lub zanikają, gdy są one na blaknięcie lub pomniejszyć)Jak wstrzymać wywołanie_queue_t i utworzone przez niego kolejki

Oto kod (fadeIn i delayFadeOut są zarówno nazywany na początku programu):

- (void) doFadeIn: (float) incriment to: (int) volume with: (AVAudioPlayer*) thisplayer on: (dispatch_queue_t) queue{ 
    dispatch_async(queue, ^{ 
     double delayInSeconds = .1; 
     dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); 
     dispatch_after(popTime, queue, ^(void){ 
      thisplayer.volume = (thisplayer.volume + incriment) < volume ? thisplayer.volume + incriment : volume; 
      NSLog([[[NSNumber alloc] initWithFloat:thisplayer.volume] stringValue]); 
      if (thisplayer.volume < volume) { 
       [self doFadeIn:incriment to:volume with:thisplayer on:queue]; 
      } 
     }); 
    });  
} 

-(void) doDelayFadeOut: (float) incriment with: (AVAudioPlayer*) thisplayer on: (dispatch_queue_t) queue 
{ 
    dispatch_async(queue, ^{ 
     double delayInSeconds = .1; 
     dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); 
     dispatch_after(popTime, queue, ^(void){ 
      thisplayer.volume = (thisplayer.volume - incriment) > 0 ? thisplayer.volume - incriment : 0; 
      NSLog([[[NSNumber alloc] initWithFloat:thisplayer.volume] stringValue]); 
      if (thisplayer.volume > 0.0) { 
       [self doDelayFadeOut:incriment with:thisplayer on:queue]; 
      } 
     }); 
    }); 
} 

-(void) fadeIn: (AVAudioPlayer*) dFade { 
    if (dFade == nil) { 
     return; 
    } 
    dispatch_queue_t queue = dispatch_queue_create("com.cue.MainFade", NULL); 
    dispatch_async(queue, ^(void){ 
     if(dFade !=nil){ 
      double incriment = ([self relativeVolume]/[self fadeIn])/10; //incriment per .1 seconds. 
      [self doFadeIn: incriment to: [self relativeVolume] with:dFade on:dispatch_queue_create("com.cue.MainFade", 0)]; 
     } 

    }); 
} 

- (void) delayFadeOut: (AVAudioPlayer*) dFade { //d-fade should be independent of other threads 
    if (dFade == nil) { 
     return; 
    } 
    int timeRun = self.duration - self.fadeOut; 
    dispatch_queue_t queue = dispatch_queue_create("com.cue.MainFade", NULL); 
    dispatch_time_t mainPopTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(timeRun * NSEC_PER_SEC)); 
    printf("test"); 
    dispatch_after(mainPopTime, queue, ^(void){ 
     if(dFade !=nil){ 
      double incriment = ([dFade volume]/[self fadeOut])/10; //incriment per .1 seconds. 
      [self doDelayFadeOut:incriment with:dFade on:dispatch_queue_create("com.cue.MainFade", 0)]; 
     } 

    }); 
    if (self.cueType == 2) { 
     [self callNext]; 
    } 
} 

Odpowiedz

9

Na ogólne pytanie, połączenie to dispatch_suspend() (wraz z dispatch_resume()). Zapobiega to planowaniu nowych bloków w określonej kolejce. Nie będzie to miało wpływu na już działające bloki. Jeśli chcesz wstrzymać blok już zaplanowany i uruchomiony, od Twojego kodu zależy sprawdzenie warunkowe i przerwa.

Kluczem do zrozumienia tego sposobu użycia jest to, że nie ma nic, co mogłoby "wstrzymać" zegar "w punkcie wysyłki". Jeśli powiesz, że chcesz wysłać coś po 1 sekundzie, to absolutnie zostanie wysłane po 1 sekundzie. Ale "wysłanie" nie oznacza "uruchomienia". Oznacza to "postawić kolejkę". Jeśli ta kolejka zostanie zawieszona, blok będzie zawieszony, dopóki kolejka nie zostanie wznowiona. Należy uważać na to, że nie chcesz, aby w bloczku kumulowały się pęknięcia bloków. Gdyby tak było, po wznowieniu kolejki wszystkie byłyby zaplanowane od początku do końca. Patrząc na twój kod, prawdopodobnie to się nie stanie, więc to może ci pomóc. Pamiętaj, że wysyłka oznacza "postawić kolejkę". Kolejki nie zawieszone mają uporządkowane bloki.

4

Aby zawiesić kolejki/anulować operacje, zamiast GCD należy użyć NSOperation i NSOperationQueue. Zobacz here.

Powiązane problemy