Using Threads in Swift
Swift provides DispatchQueue as an excellent layer above raw threads. But sometimes you want to create a new thread dedicated to some specific task. Or maybe implement your own concurrent executor. Swift gives you access to raw threads and in this article, I'll show how to use it.
Thread
Creating a thread in Swift is pretty simple using Thread
class. You can either specify objc
function through a selector as a starting point, or pass a closure, and, more convenient way, subclass Thread
.
The thread is not started when the initializer is called. You need to call start()
method explicitly to start the thread.
The thread runs despite its handle returned by Thread
initializer. That's it — the variable can no longer exist and the thread will still run. That's fine, but you will lose the ability to control the thread: check if it's completed, wait for its completion, cancel it, etc.
Wait for completion, join a thread
Swift does not provide a way to wait for the thread's completion.
To wait for thread completion, we can join threads using DispatchGroup
class MyThread: Thread {
let waiter = DispatchGroup()
override func start() {
waiter.enter()
super.start()
}
override func main() {
task()
waiter.leave()
}
func task() {
print("Hi from thread")
}
func join() {
waiter.wait()
}
}
let thread = MyThread()
thread.start()
thread.join() // Waits for thread completion
Terminate the thread
The thread terminates automatically after reaching main
's end. To exit the thread in advance, you can call Thread.exit()
function from the thread. To use it correctly with created DispatchGroup
, it's better to create a custom exit method:
class MyThread: Thread {
...
func exit() {
waiter.leave()
Thread.exit()
}
...
}
Cancel the thread
Apart from terminating the thread, you can cancel it, by calling cancel()
method on the thread's handle or inside the thread itself. This sets isCancelled
property to true
.