Objective c 是否将NSOperationQueue用作后进先出堆栈?

Objective c 是否将NSOperationQueue用作后进先出堆栈?,objective-c,ios,nsoperationqueue,Objective C,Ios,Nsoperationqueue,我需要做一系列的url调用(获取WMS分幅)。我想使用后进先出堆栈,所以最新的url调用是最重要的。我想现在在屏幕上显示瓷砖,而不是5秒前平移后屏幕上的瓷砖 我可以从NSMutableArray创建自己的堆栈,但我想知道NSOperationQueue是否可以用作后进先出堆栈?不幸的是,我认为NSOperationQueues,顾名思义,只能用作队列,不能用作堆栈。为了避免执行大量的手动任务编组,最简单的方法可能是将队列视为不可变的,并通过复制进行变异。例如 - (NSOperationQueu

我需要做一系列的url调用(获取WMS分幅)。我想使用后进先出堆栈,所以最新的url调用是最重要的。我想现在在屏幕上显示瓷砖,而不是5秒前平移后屏幕上的瓷砖


我可以从NSMutableArray创建自己的堆栈,但我想知道NSOperationQueue是否可以用作后进先出堆栈?

不幸的是,我认为
NSOperationQueue
s,顾名思义,只能用作队列,不能用作堆栈。为了避免执行大量的手动任务编组,最简单的方法可能是将队列视为不可变的,并通过复制进行变异。例如

- (NSOperationQueue *)addOperation:(NSOperation *)operation toHeadOfQueue:(NSOperationQueue *)queue
{
    // suspending a queue prevents it from issuing new operations; it doesn't
    // pause any already ongoing operations. So we do this to prevent a race
    // condition as we copy operations from the queue
    queue.suspended = YES;

    // create a new queue
    NSOperationQueue *mutatedQueue = [[NSOperationQueue alloc] init];

    // add the new operation at the head
    [mutatedQueue addOperation:operation];

    // copy in all the preexisting operations that haven't yet started
    for(NSOperation *operation in [queue operations])
    {
        if(!operation.isExecuting)
            [mutatedQueue addOperation:operation];
    }

    // the caller should now ensure the original queue is disposed of...
}

/* ... elsewhere ... */

NSOperationQueue *newQueue = [self addOperation:newOperation toHeadOfQueue:operationQueue];
[operationQueue release];
operationQueue = newQueue;

目前看来,释放一个仍在工作的队列(旧操作队列也会发生这种情况)并不会导致它取消所有操作,但这不是记录在案的行为,因此可能不可信。如果您希望真正安全,请使用键值观察旧队列上的
operationCount
属性,并在其变为零时释放该属性。

您可以使用
-[NSOperation setQueuePriority:
设置操作队列中操作的优先级。每次添加操作时,您都必须重新调整现有操作的优先级,但您可以实现所需的功能。基本上,您会将所有旧的问题降级,并给予最新的一个最高优先级。

我不确定您是否仍在寻找解决方案,但我发现同样的问题困扰了我一段时间,所以我继续在这里实现了一个操作堆栈:。我已经在几百次下载操作中使用过它,而且它运行得很好

遗憾的是,如果不遇到一些棘手的问题,你就无法做到这一点,因为:

重要信息在运行操作或将其添加到操作队列之前,应始终配置依赖项。之后添加的依赖项可能不会阻止给定的操作对象运行。(发件人:)


看看这个相关的问题:

在NSOperationQueue之上找到了一个堆栈/后进先出功能的简洁实现。它可以用作扩展NSOperationQueue或NSOperationQueue LIFO子类的类别


最简单的方法是将操作和要处理的数据分开,这样就可以像往常一样将操作添加到NSOperationQueue,然后从堆栈或任何其他需要的数据结构中获取数据

var tasks: [MyTask]
...

func startOperation() {
    myQueue.addOperation {
        guard let task = tasks.last else {
            return
        }

        tasks.removeLast()

        task.perform()
    }
}

现在,显然,您可能需要确保tasks集合可以并发使用,但这是许多预先制作的解决方案中的一个更常见的问题,而不是绕过NSOperationQueue执行顺序。

我相信这会起作用,我决定从NSMutableArray创建自己的堆栈。感谢您的输入。根据记录,我本来可以避免创建自己的堆栈,因为您需要负责发布操作并监控其进度,也就是说,您最终会重新实现许多
NSOperationQueue
已经完成的操作。如果您使用的是并发操作,那么效率肯定会降低。显然,这些都与您的具体需求无关,我相信您做的是正确的,我只是想说这是为了完整性。我正在创建一个URL堆栈,需要调用WMS互动程序。我检查是否有X磁贴,如果它不在缓存中,我将URL放在堆栈上。我有一个计时器,每2秒触发一次,它将创建请求并将其放入GDC队列中执行。这很有可能不起作用-不能保证
操作
数组按照它们添加的顺序包含操作。由于依赖关系和不同的优先级,添加的顺序操作也不一定是它们执行的顺序。引用苹果的文档:您应该仅在需要时使用优先级值来分类非依赖操作的相对优先级。优先级值不应用于实现不同操作对象之间的依赖关系管理。在此处找到:。尝试使用setQueuePriority设置顺序已使用random完成execution@MichalGumny,Apple doc的报价证实了我的建议。我们试图“对非相关操作的相对优先级进行分类”。我们没有试图实现依赖关系管理。如果队列未挂起,则可以在添加操作后或低于其最大并发度时立即启动操作。如果你提到的另一个问题暂停了排队,它会很好地工作。队列可以随时启动操作,显然,更改操作优先级不会改变已经发生的事情。但当选择一个新的操作开始时,优先级是被尊重的。问题是后进先出顺序,苹果写了“相对优先级”,我认为这表明我们不能100%肯定优先级顺序会被保留。我甚至写了一些代码来检查它,但顺序并不像想象的那样。Ofc I可能是错误的,如果是这种情况,请使用
-[NSOperationQueue setSuspended:
而不是
-setMaxConcurrentOperationCount:
0
进行更正。我认为没有理由相信后者会有效地暂停排队。“相对优先权”并不意味着它可能不被遵守。这仅仅意味着优先级值在任何绝对尺度上都没有意义,而只是在相互比较时才有意义。当队列准备好启动新操作时,它肯定会选择优先级最高的就绪操作。由于并发的性质,可能存在争用条件,但除此之外,优先级将得到尊重。从:“队列中的操作……根据优先级级别……组织……并相应地执行。”“对于准备好执行的操作,操作队列始终执行相对于其他准备好的操作具有最高优先级的操作。”“操作队列根据I执行其排队的操作对象