首先,我创建一个串行队列,如下所示
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。
换句话说,如果我添加了一个新的任务,我希望将任何等待的任务(不是当前正在运行的任务)从队列中弹出。
有没有内置的机制,或者我必须自己实现它?对于后者,我如何识别队列中的单个任务并删除它们?
发布于 2012-09-07 22:39:45
一旦一个块被提交到GCD分派队列,它就会运行。没有办法取消它。正如您所知道的,您可以实现自己的机制来提前“中止”块执行。
一种更简单的方法是使用NSOperationQueue
,因为它已经提供了取消挂起操作(即那些尚未运行的操作)的实现,并且您可以使用新的addOperationWithBlock
方法轻松地将块排队。
虽然NSOperationQueue
是使用GCD实现的,但我发现GCD在大多数情况下更容易使用。然而,在这种情况下,我会认真考虑使用NSOperationQueue
,因为它已经处理了取消挂起的操作。
发布于 2012-09-07 20:26:53
有了Davids answer让我走上正轨,我成功地这样做了
taskCounter++;
dispatch_async(queue, ^{
if (taskCounter > 1) {
taskCounter--;
NSLog(@"%@", @"skip");
return;
}
NSLog(@"%@", @"start");
// do stuff
sleep(3);
taskCounter--;
NSLog(@"%@", @"done");
});
taskCounter
必须是一个ivar或一个属性(用0
初始化)。在这种情况下,它甚至不需要__block
属性。
发布于 2012-09-07 19:28:15
处理这种情况的方法是使用ivar,它向排队的块指示它们应该只返回:
^{
if(!canceled) {
... do work
}
}
你也不需要使用简单的布尔值--你可以让它变得更复杂--但一般的想法是在做任何事情之前使用一个或多个ivars来查询块。
我使用这种技术(但不是我发明的)取得了巨大的成功。
https://stackoverflow.com/questions/12317154
复制相似问题