iosswiftnsoperationqueue

Invalid order of first low priority operation in NSOperationQueue


Really wondering, why the position of the first operation isn't changed after changing the suspended state to false.

    let operationQueue = OperationQueue.main

    let operation1 = BlockOperation { print("1") }
    operation1.queuePriority = .low

    let operation2 = BlockOperation { print("2") }
    operation2.queuePriority = .normal

    let operation3 = BlockOperation { print("3") }
    operation3.queuePriority = .high

    let operation4 = BlockOperation { print("4") }
    operation4.queuePriority = .veryHigh

    operationQueue.isSuspended = true
    operationQueue.addOperation(operation1)
    operationQueue.addOperation(operation2)
    operationQueue.addOperation(operation3)
    operationQueue.addOperation(operation4)
    operationQueue.isSuspended = false

Print output:

1
4
3
2

Expected print output:

4
3
2
1

UPD Noticed this behavior only for OperationQueue.main. For custom OperationQueue() with maxConcurrentOperationCount = 1 works as expected.


Solution

  • You cannot suspend .main. That's a system queue.

    This is more explicitly explained in the documentation for the underlying DispatchQueue.main:

    As with the global concurrent queues, calls to suspend(), resume(), dispatch_set_context(::), and the like have no effect when used on the queue in this property.

    When you schedule the first task, the queue is empty, and it's the highest priority, so it's immediately scheduled. When there are pending tasks in the queue, they get ordered by priority, though this isn't promised. If you need an order, you use dependencies, not priorities. Priorities are a hint, and in my experience, should generally be avoided unless you have a very specialized problem.

    In the case of your custom queue, it really is suspended, so the first task doesn't get scheduled as soon as you enqueue it.