I am executing set of tasks, and in order to span them over time I've used Thread.sleep(forTimeInterval: ... )
It adds pauses between executions.
Then, on the main screen I have controllers, that can intervene into thread execution, so when controller applied I want to cancel the sleep. And start from the place of user's choice.
So, I've tried
Thread.exit()
- and it terminates the program with error.
How to exit (or, refresh) the current thread and start from the place I want? What are the ways to control the suspension of thread by button (i.e. controller)?
What actually happens is that if I cancel, it continues to run just from the same place...
let queue = DispatchQueue(label: "Actions Queue")
let delay: Double = 5
var actions = ["action 1", "action 2", "action 3", "action 4", "action 5"]
// every time task finishes, it calls for the following task (with delay)
queue.sync {
// sets an interval, that continues an action
Thread.sleep(forTimeInterval: TimeInterval(delay))
// continue an action
}
// heres how I've tried in main view, but it doesn't work
queue.sync {
Thread.current.cancel()
}
EDITS:
For example, what does the cancel()
do here? and why exit()
can't be applied to Thread.current
, but only to Thread.
"You can use these semantics to cancel the execution of a thread or determine if the thread is still executing or has finished its task". Okey, if I cancel()
. What, then will start it again?
queue.sync {
Thread.sleep(forTimeInterval: TimeInterval(10.0))
// do something
}
Button("...") {
queue.sync {
Thread.current.cancel()
}
}
As a general rule, I would advise against sleeping on a thread. First, we do not have preemptive cancelation. Second, it’s an inefficient use of resources, tying up that thread unnecessarily.
If you want to do something after a certain period of time, you have a few options:
Schedule a
Timer
and theninvalidate
it if you want to stop it.If using Swift concurrency (e.g.,
Task
,async
-await
, etc.), you canTask.sleep
, which, unlikeThread.sleep
, detects and handles cancelation.Thread.sleep
should be avoided, but with Swift concurrency, you can store theTask
in a property,cancel
it when appropriate, andTask.sleep
within theTask
will handle cancellation elegantly.You can create a
DispatchWorkItem
, dispatch it withasyncAfter
, and thencancel
if you don’t want that to happen.If you have some cancelable tasks that you want to perform every x seconds, a single repeating
Timer
is probably easiest, as you caninvalidate
it and it stops the whole repeating series in one step. (It also avoids timer coalescing problems.)You said:
I would suggest a repeating
Timer
to advance to the next slide. If the user manually changes to another slide,invalidate
the old timer and create a new repeatingTimer
.