This code is experimental as a study on how to block execution with attempts to break functionality. This code may work incidentally, not by proper execution of a thread-safe solution. This Gist will be updated later when more time can be put into better examples. In the meantime, the following Gist can be referenced.
https://gist.github.com/brennanMKE/e29e6d305cf03978b9f9e084296f2124
Asynchronous code does not operate as simply as code which runs on the main thread linearly. Concurrency can complicate code which must defer execution until the asynchronous work has completed. A common pattern is to include a closure parameter with a function which is executed once the asynchronous work has completed inside the function. This closure, often called a completion handler, requires calls to such functions to use nested closures to allow for deferring execution until the work has completed.
At times it is necessary to add asynchronous work to a code base which did not have it before requiring changes to all of the calls to code which would have to be changed to use completion handlers. This kind of change is disruptive. One way to avoid using a completion handler is to block execution after the asynchronous work has completed and before the end of the function. Outside the function it appears to be a regular, non-asynchronous function.
The snippets of code included here make a function that blocks execution before returning which also runs code asynchronously in a queue off the main thread. The examples include the following.
- DispatchSemaphore
- DispatchGroup
- DispatchWorkItem
- Async (non-blocking)
Each example can be copied into a Playground to explore how they function.
The blocking functions behave as though no asynchronous work is being done. No completion handler is needed which simplifies using the function. The example using DispatchSemaphore
is the most complex as it requires calling wait
and then signal
at the end of the closure. Both the DispatchGroup
and DispatchWorkItem
examples will resume execution automatically when the closure returns.
Most of the time execution is running on the main thread. Any time the UI is updated it must be done on the main thread. With the Dispatch framework threads of execution are organized into queues, with one queue being the main queue. It is a serial queue which operates on the main thread.
Print statements include a count to show the current value of the count property stored with the class. The DispatchSemaphore
and DispatchGroup
examples print output which orders the "Work" and "Done" print statements in order while the 3rd example, which does not block execution, prints the statements in an unordered sequence. It demonstrates that execution continues without blocking as it shows the current value of the count when it prints the "Done" statement.