8

i need to do a series of url calls (fetching WMS tiles). i want to use a LIFO stack so the newest url call is the most important. i want to display the tile on the screen now, not a tile that was on the screen 5 seconds ago after a pan.

i can create my own stack from a NSMutableArray, but i'm wondering if a NSOperationQueue can be used as a LIFO stack?

4

6 回答 6

5

您可以使用 设置操作队列中操作的优先级-[NSOperation setQueuePriority:]。每次添加操作时,您都必须重新调整现有操作的优先级,但您可以实现您正在寻找的东西。您基本上会降级所有旧的并给予最新的最高优先级。

于 2012-04-10T05:35:16.787 回答
3

遗憾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;

目前看来,释放仍在工作的队列(就像旧的操作队列会发生的那样)不会导致它取消所有操作,但这不是记录在案的行为,因此可能不值得信赖。如果你想真正安全,key-value 观察operationCount旧队列上的属性,当它变为零时释放它。

于 2012-04-09T19:36:13.127 回答
1

可悲的是,如果不遇到一些棘手的问题,您就无法做到这一点,因为:

重要在运行操作或将它们添加到操作队列之前,您应该始终配置依赖项。之后添加的依赖项可能不会阻止给定的操作对象运行。(来自:并发编程指南:配置互操作依赖

看看这个相关的问题:AFURLConnectionOperation 'start' 方法在它准备好之前被调用,之后再也不会被调用

于 2013-02-13T23:38:05.670 回答
1

我不确定你是否还在寻找解决方案,但我同样的问题一直困扰着我一段时间,所以我继续在这里实现了一个操作堆栈:https ://github.com/cbrauchli/ CBOperationStack。我已经使用它进行了数百次下载操作,并且效果很好。

于 2012-10-03T20:31:48.107 回答
0

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

https://github.com/nicklockwood/NSOperationStack

于 2013-08-21T16:58:09.643 回答
0

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

var tasks: [MyTask]
...

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

        tasks.removeLast()

        task.perform()
    }
}

现在,显然,您可能需要确保可以同时使用任务集合,但是对于许多预制解决方案来说,这是一个比绕过 NSOperationQueue 执行顺序更常见的问题。

于 2020-01-20T12:52:54.567 回答