如何暂停dispatch_queue_t及其创建的队列

sin*_*inθ 5 multithreading cocoa-touch objective-c ios

我正在创建一个程序,可以在其他内容中淡入淡出音乐.问题是其他线程/队列可以暂停音乐,这意味着淡入和淡出也不仅需要暂停,还需要暂停.我需要能够在dispatch_after上暂停"定时器"(因为这是在音乐开始播放时调用,以便告诉它何时开始淡出,如果它被暂停则需要延迟)并暂停队列本身(为了暂停淡入或淡出,当它们淡入或淡出时)

这是代码(fadeIn和delayFadeOut都在程序开头调用):

- (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];
    }
}
Run Code Online (Sandbox Code Playgroud)

Rob*_*ier 10

对于您的一般问题,电话是dispatch_suspend()(连同dispatch_resume()).这将防止特定队列上的任何新块被调度.它对已经运行的块没有任何影响.如果要暂停已调度并正在运行的块,则需要检查某些条件和暂停代码.

但是,了解何时使用它的关键是,没有任何东西可以在dispatch_after上"暂停"计时器.如果你说你希望在1秒后发送一些东西,它绝对会在1秒后发送.但"派遣"并不意味着"跑".这意味着"排队".如果该队列被挂起,则该块将挂起,直到队列恢复.需要注意的是,您不希望在队列中累积一堆淡入淡出块.如果他们这样做了,当你恢复队列时,他们都将被安排背靠背.看看你的代码,这可能不会发生,所以这可能对你有用.请记住,调度意味着"排队".非暂停队列按顺序安排其块.


fum*_*007 6

对于挂起队列/取消操作,应使用NSOperationNSOperationQueue而不是GCD。看这里