Dispatch Framework

Dispatch for Android and iOS - Working with concurrency and background threads in Android and iOS

Introduction

The dispatch framework is a library for writing code for asynchronous processing. It allows you to run code in the background and invoke functions asynchronously. SCADE ported the dispatch framework to Android and ensures that is works on x86/ARM for both 32 and 64bit.

Your Swift code is 100% same for both iOS and Android. There are no difference.

๐Ÿ‘

Example Code

Please see the UgSystemDemo/Dispatch project for the source code created in this chapter. See Installing examples for information on how to download the examples.

Understanding dispatch

This is not a full tutorial on the advanced concepts of dispatch, but a simple example driven guide. There are many other articles out on the internet to read. Here are some examples. Please ensure that you understand concepts such as DispatchQueue,work item.

Getting started

So our goal is to run code asynchronously. You can queue your code for execution and Dispatch takes care of the correct sequence of execution based on priorities:

Queues

The queues you deal most with are the main queue and the global queue:

The main queue

  • is used for UI tasks
  • is a serial queue, that means tasks are queued and executed one after the other

The global queue

  • is used for stuff that is non-UI related
  • is a concurrent queue, that means the tasks are executed in parallel
  • is used for non-ui tasks such as IO and database operations, long running calculations
// Use global queue to execute code asynchronously in the background
DispatchQueue.global(qos: .background).async {
	print("background: \(Thread.current)")
}

Run tasks in the main queue. There are not many good reasons to use the main queue alone. Most of the time we use it to update the UI with results from a long running task:

DispatchQueue.global(qos: .background).async {
	// do your long running background job here
	print("running long running iO job  : background: \(Thread.current)")
				 
   DispatchQueue.main.async {
   	  // then update your UI here
   }
}

Queue priorities - Quality of Service

The code that you want to execute asynchronously is called task or work item in Dispatch speak. The priority with which the code is executed depends on the quality of service settings. There are four different quality of services

  • .userInteractive (highest priority)
  • .userInitiated
  • .utility
  • .background (lowest priority)

Executing code with delay

Dispatch has many other functionalities. From instance, tell Dispatch to run a task only after some time.

// run tasks in background with delay
let inTwoSeconds = DispatchTime.now() + .seconds(2)
		
DispatchQueue.global(qos: .background).asyncAfter(deadline: inTwoSeconds) {
	print("ran this after two seconds : background: \(Thread.current)")
}

Canceling a long running task

Let's say you are retrieving data, but for some reason need to interrupt this long running process. You use the DispatchWorkItem class to achieve this

// Example 4: Cancel a tasks after some time.
		// Create task that runs for long time
		var myWorkItem : DispatchWorkItem?
		myWorkItem = DispatchWorkItem {
	    	for i in 1...5 {
		        guard let item = myWorkItem, !item.isCancelled else {
		            print("Example 4 : workitem was canceled")
		            break
	       		 }
		         // wait one second
	      		 sleep(1)
	       		 print("Example 4: waiting \(i)")
    		}
		}

		// inform when workitem is done
		myWorkItem?.notify(queue: .main) {
		    print("Example 4 : I am done with my job")
		}

		// start workitem and cancel later
		let cancelAfter = DispatchTime.now() + .seconds(2)
		DispatchQueue.global().asyncAfter(deadline: cancelAfter) {
		    myWorkItem?.cancel()
		}
		
		// Run workitem
		DispatchQueue.main.async(execute: myWorkItem!)

What's next

This guide showed the fully working Dispatch framework. We appreciate your questions and comments.