swiftmultithreadingcombineoperationqueue

print 1 to 10 in OperationQueue don't print whole number


I'm studying Combine Scheduler and I have this example code from Raywenderlich book

let queue = OperationQueue()

let subscription = (1...10).publisher
  .receive(on: queue)
  .sink { value in
    print("Received \(value) on thread \(Thread.current.number)")
  }

The book is explaining that OperationQueue uses all available threads so the print order and thread could be random. I understand that part but when I run this code in my playground, I see only 5 numbers out of 10.

Received 1 on thread 7
Received 2 on thread 6
Received 3 on thread 5
Received 7 on thread 9
Received 6 on thread 4

Why that code doesn't show all 10 numbers??


Solution

  • You need to import PlaygroundSupport and set PlaygroundPage.current.needsIndefiniteExecution = true at the top of the file.

    If you use the other sink method, the one that you also get a completion handler block for, then in that completion handler you should call PlaygroundPage.current.finishExecution()

    Edit: Call PlaygroundPage.current.finishExecution() in a barrier block on the queue, otherwise that gets called before your print statements all execute.

    Here's my testing code:

    PlaygroundPage.current.needsIndefiniteExecution = true
    
    let queue = OperationQueue()
    
    let subscription = (1...10).publisher
        .receive(on: queue)
        .sink(receiveCompletion: { _ in
            queue.addBarrierBlock {
                print("Finished")
                PlaygroundPage.current.finishExecution()
            }
        }, receiveValue: { value in
            print("Received \(value) on thread \(Thread.current)")
        })
    

    And the output:

    Received 1 on thread <NSThread: 0x7fd86f204080>{number = 2, name = (null)}
    Received 2 on thread <NSThread: 0x7fd86f404340>{number = 3, name = (null)}
    Received 3 on thread <NSThread: 0x7fd86f404430>{number = 4, name = (null)}
    Received 7 on thread <NSThread: 0x7fd86f405240>{number = 5, name = (null)}
    Received 6 on thread <NSThread: 0x7fd86f205c50>{number = 6, name = (null)}
    Received 10 on thread <NSThread: 0x7fd86ce487f0>{number = 7, name = (null)}
    Received 5 on thread <NSThread: 0x7fd86cf048a0>{number = 10, name = (null)}
    Received 9 on thread <NSThread: 0x7fd86ce49b20>{number = 11, name = (null)}
    Received 4 on thread <NSThread: 0x7fd86cf2a4c0>{number = 12, name = (null)}
    Received 8 on thread <NSThread: 0x7fd86ce4ad60>{number = 13, name = (null)}
    Finished