Long-running Task lifetime

Having stumbled across this thread I have some questions about performing a long running Task which executes work periodically.

Using the following code as an example:

longRunningTask = Task {
    while !Task.isCancelled {
        await performPeriodicAction()
        try? await Task.sleep(for: .seconds(10))
    }
}

My questions are essentially:

  1. First and foremost, is this considered a sound approach for this sort of work, or is there a more idiomatic pattern I should be reaching for?
  2. What sort of guarantees are given with regards to the above tasks lifetime? Taking iOS as an example, can I be guaranteed the Task will suspend during backgrounding and resume on foregrounding indefinitely (i.e: survive the lifetime of the process) if I do not explicitly cancel it?
  3. If the answer to the former question is no, what is the best way to handle this scenario?

That seems fine. One thing to note is that if you need the repeating 10 second interval to not drift slightly over time, you may need to use an actual repeating timer rather than repeated sleeps. I'm guessing being very precise isn't important here though.

2 Likes

I use this exact pattern for long running, imprecise timers, and it works pretty well. They do resume from the background on iOS. Two things I'll note. First, if you can use a Clock for your sleep, you can use swift-clocks and its TestClock to help test your timers (their swift-dependencies library helps there too). Second, if you wrap your call to performPeriodicAction in withTaskCancellationHandler you can ensure the action you're performing properly respects cancellation when longRunningTask is canceled. This ensures you can start and stop the timer and not worry about the work continuing anyway.

2 Likes