GCD:如何从串行队列中删除等待的任务?

首先我创build一个像这样的串行队列

static dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL); 

那么,在某个未知的时间点,任务就会像这样被添加到队列中

 dispatch_async(queue, ^{ // do something, which takes some time }); 

如果第一个任务尚未完成,则新任务将等到第一个任务完成(这当然是串行队列的目的)。

但是,如果我向队列中添加5个新任务,而原来的第一个仍在运行,我不想执行新的任务1号,然后2号,然后3号等等,但是想要得到摆脱任务1到4,并在原来的第一个任务完成后直接开始执行任务5。

换句话说,如果我添加一个新的队列,我想popup队列中的任何正在等待的任务(不是正在运行的任务)。

有没有build立这样的机制,还是我必须自己实现这个? 对于后者,我将如何识别队列中的单个任务并将其删除?

一旦一个块被提交给一个GCD调度队列,它就会运行。 没有办法取消它。 如您所知,您可以实现自己的机制,以尽早“中止”块的执行。

一个更简单的方法是使用NSOperationQueue ,因为它已经提供了一个取消挂起操作的实现(即那些还没有运行的操作),你可以用new-ish addOperationWithBlock方法轻松地排队。

虽然NSOperationQueue是使用GCD实现的,但我发现在大多数情况下GCD更容易使用。 但是,在这种情况下,我会认真考虑使用NSOperationQueue因为它已经处理取消挂起的操作。

戴维斯回答让我走上正轨,我成功地做到了这一点

 taskCounter++; dispatch_async(queue, ^{ if (taskCounter > 1) { taskCounter--; NSLog(@"%@", @"skip"); return; } NSLog(@"%@", @"start"); // do stuff sleep(3); taskCounter--; NSLog(@"%@", @"done"); }); 

taskCounter必须是伊娃或属性(用0初始化它)。 在这种情况下,它甚至不需要__block属性。

你处理这个问题的方法是使用一个ivar,指示他们应该返回的排队块:

 ^{ if(!canceled) { ... do work } } 

你不需要使用一个简单的布尔值 – 你可以使这个更复杂 – 但总的想法是使用一个或多个ivars,块做任何事情之前查询。

我使用这种技术(但没有发明),取得了巨大的成功。