【问题标题】:GCD: How to remove waiting tasks from serial queue?GCD:如何从串行队列中删除等待任务?
【发布时间】:2012-09-01 06:44:53
【问题描述】:

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

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

然后,在某个未知的时间点,像这样将任务添加到队列中

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

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

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

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

是否有内置机制,还是我必须自己实现?而对于后者,我将如何识别队列中的单个任务并删除它们?

【问题讨论】:

    标签: objective-c ios grand-central-dispatch


    【解决方案1】:

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

    一个更简单的方法是使用NSOperationQueue,因为它已经提供了一个用于取消挂起操作(即那些尚未运行的操作)的实现,并且您可以使用新的@987654322 轻松地将块排入队列@方法。

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

    【讨论】:

      【解决方案2】:

      随着戴维斯的回答让我走上正轨,我成功地这样做了

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

      taskCounter 必须是 ivar 或属性(使用 0 对其进行初始化)。在这种情况下,它甚至不需要__block 属性。

      【讨论】:

      • 我一直忘记,当你在一个块中有一个 ivar(不使用'self.')时,编译器实际上会生成代码'self->ivar',因此它会保留 self 和你说不需要'__block'(这在ObjectiveC Apple listserv上讨论过,我提出了为什么它工作的问题!)
      • 我相信你知道,但是那个实现不是线程安全的。如果多个线程调用此代码,您将丢弃您的 taskCounter。
      • 是的,没错。在我面临的场景中不需要是线程安全的,但你绝对是对的。另外,感谢NSOperationQueues 的分析。我会考虑改用它们,但还有其他事情需要先处理;)
      【解决方案3】:

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

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

      您也不需要使用简单的布尔值 - 您可以使其更复杂 - 但总体思路是在执行任何操作之前使用一个或多个块查询的 ivars。

      我使用这种技术(但不是发明它)取得了巨大成功。

      【讨论】:

        猜你喜欢
        • 2013-11-20
        • 1970-01-01
        • 2017-03-01
        • 2011-12-13
        • 1970-01-01
        • 2012-09-26
        • 2019-08-21
        • 1970-01-01
        • 2020-12-16
        相关资源
        最近更新 更多