GCD: How to remove waiting tasks from serial queue?

故事扮演 提交于 2019-12-03 12:21:51

Once a block has been submitted to a GCD dispatch queue, it will run. There is no way to cancel it. You can, as you know, implement your own mechanism to "abort" the block execution early.

An easier way to do this would be to use NSOperationQueue, as it already provides an implementation for canceling pending operations (i.e., those not yet running), and you can easily enqueue a block with the new-ish addOperationWithBlock method.

Though NSOperationQueue is implemented using GCD, I find GCD much easier to use in most cases. However, in this case, I would seriously consider using NSOperationQueue because it already handles canceling pending operations.

With Davids answer getting me on track I succeeded in doing this like so

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

taskCounter has to be either an ivar or a property (initialize it with 0). In that case it doesn't even need the __block attribute.

The way you handle this is to use an ivar that indicates to the queued blocks they should just return:

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

You don't need to use a simple boolean either - you can make this more complex - but the general idea is to use one or more ivars that the block queries before doing anything.

I use this technique (but did not invent it) with great success.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!