One thing I can't fully understand, why this code don't cause a deadlock:
let queue = DispatchQueue(label: "queue_label")
print("\(Thread.current)") // <_NSMainThread: 0x60000051c440>{number = 1, name = main}
queue.sync {
self.view.backgroundColor = .red // ok
print("in sync \(Thread.current)") // <_NSMainThread: 0x60000051c440>{number = 1, name = main}
}
sync task performed by serial main thread - we see it by print statement and we can additionally prove it by successfully change UI (backgroundColor).
If we change queue.sync to DisptachQueue.main.sync - we of course get a deadlock. What's the difference here?
Post
Replies
Boosts
Views
Activity
Threads and queues are different things. When you enqueue a block on a queue, Dispatch arranges to have a thread run it at some point.
So, difference between queue.sync and DisptachQueue.main.sync in my case is that when using queue.sync, Dispatch sees that some work needs to be executed on a serial queue and wants to be executed synchronously, it knows that now we are on the main thread and that thread is not going to be doing anything useful which waiting for that block to complete, so it schedules this work on main thread after all existed work on this thread is complete. And because of that - there is no deadlock.
On the other hands, when use DisptachQueue.main.sync directly, Dispatch do not wait work to complete on main thread and try to add this block to execute right now - and this cause a deadlock.
How far my conclusions from truth?
I can't still understand relation between main thread and main queue in this scenario.
Queue - entity that rules pool of threads entities to execute blocks. Thread - entity that execute actual work. Right?
However, the work never completes because the thing that would be servicing the main queue, the main thread, is blocked waiting for itself.
When we call DispatchQueue.main.sync we said: start doing this peace of work on main queue (and on main thread) and don't return until you finish. And we get deadlock.
When we call myCustomSerialQueue.sync we said: start doing this peace of work on myCustomSerialQueue queue (and on main thread because of sync optimization in our scenario) and don't return until you finish. And here there's no deadlock.
In both cases block runs on main thread.
Difference is that in DispatchQueue.main.sync case under the hood starts some semaphore that block further execution, until incoming block is finished, and it will await indefinitely - we get deadlock and crash.
With myCustomSerialQueue.sync case we just reusing the blocked thread (main thread) to run the block and got no deadlock.
Did I get it right?
It turns out than I've used the same MapTemplate to create new navigationSession after disconnecting and reconnecting InterfaceController - MapTemplate needs to be recreated.