In Swift, I used this kind of pattern sometimes.
DispatchQueue.global().async { // do stuff in background, concurrent thread DispatchQueue.main.sync { // update UI } }
The purpose of this pattern is clear. Do time consuming calculation in global thread so UI is not locked and update UI in main thread after calculation is done.
What if there's nothing to calculate? I just found a logic in my project which
//A DispatchQueue.main.sync { // do something }
crashes but
// B DispatchQueue.global().async { DispatchQueue.main.sync { // do something } }
doesn't crash.
How are they different? And Is case B different with just this?
// C DispatchQueue.main.async { // do something }
And one more question. I know main thread is serial queue, but if I run multiple code block in multiple main.async
, it works like concurrent queue.
DispatchQueue.main.async { // do A } DispatchQueue.main.async { // do B }
If main thread is really a serial queue, how can they run simultaneously? If it is just a time slicing than how are they different with global concurrent queue other than main thread can update UI?
There are background threads for heavy tasks. DispatchQueue. global() runs these kind of tasks in background threads. You can tell the queue about how important your task is, so that DispatchQueue can prioritize your task. You can do this by providing Quality-of-Service information.
Use sync function for read to block current thread, while using async function with barrier flag for write to return to current queue. This is good for when multiple reads is preferred when there is no write. When write with barrier comes into the queue, other operations must wait.
Async never schedules your method to run on a background thread. The only way to do that is using something like Task. Run , which is explicitly for that purpose. In the case of a UI application, that means the code before the first await runs in the UI thread.
The main queue is the dispatch queue in which all the UI updates take place and the code involving UI changes are placed. You need to get to the main queue in order to update UI on completion of an asynchronous process like NSURLSession.
x.sync
means that the calling queue will pause and wait until the sync block finishes to continue. so in your example:
DispatchQueue.global().async { // yada yada something DispatchQueue.main.sync { // update UI } // this will happen only after 'update UI' has finished executing }
Usually you don't need to sync
back to main, async is probably good enough and safer to avoid deadlocks. Unless it is a special case where you need to wait until something finishes on main before continuing with your async task.
As for A example crashing - calling sync and targeting current queue is a deadlock (calling queue waits for the sync block to finish, but it does not start because target queue (same) is busy waiting for the sync
call to finish) and thats probably why the crash.
As for scheduling multiple blocks on main queue with async: they won't be run in parallel - they will happen one after another. Also don't assume that queue == thread. Scheduling multiple blocks onto the same queue, might create as many threads as system allow. Just the main queue is special that it utilises Main thread.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With