With the async
and await
keywords in Swift 5.9, we can specify how methods can be run in parallel. And when needed, async
methods can be run on multiple threads.
To run many tasks at once, it is helpful to use a task group. The withTaskGroup
method, and addTask
, can be used to create many threads and join them together.
Suppose we have 100 large text files and want to count the lines in all of them. We can create an async
method to count lines, and run it on many separate CPU cores.
await
" keyword to call withTaskGroup
. We pass a closure argument and call the TaskGroup
"group."addTask
—the closure argument calls the countLines
method.for
-await
loop, we join together all the tasks from the TaskGroup
, and sum all their Int
results.import Foundation func countLines(path: String) async -> Int { // Read file. let contents = try? NSString(contentsOfFile: path, encoding: String.Encoding.ascii.rawValue) // Count lines in file. var count = 0 contents!.enumerateLines({ (line, stop) -> () in count += 1 }) return count } // Step 1: repeat the path of the file to access many times in an array. var paths: [String] = []; for _ in 0...100 { paths.append("programs/words.txt") } // Step 2: call waitTaskGroup with await keyword closure argument. await withTaskGroup(of: Int.self) { group in // Step 3: add tasks with addTask, calling an async function with await. for path in paths { group.addTask { return await countLines(path: path) } } // Step 4: await all results in a for loop and sum up the total lines counted. var total = 0 for await count in group { total += count } print("Total lines counted: \(total)") }Total lines counted: 17454820
To ensure that the CPU cores were all participating, I measured the process in Process Explorer in Windows. The CPU did not reach 100%, but it used most of the cores.
With the async
and await
keywords, closure arguments, and withTaskGroup
and addTask
, we can implement powerful multithreading in Swift programs.