Immediate tasks in Swift Concurrency explained
Article Summary
Antoine van der Lee tackles a subtle but powerful new Swift 6.2 feature that most developers will misuse. Task.immediate promises faster execution, but it can easily freeze your UI if you're not careful.
Swift 6.2 introduces immediate tasks through SE-472, allowing tasks to start synchronously on the caller's execution context instead of being scheduled for later. This addresses specific performance scenarios where the standard task scheduling delay is problematic, particularly when bridging synchronous and async code on the same actor.
Key Takeaways
- Task.immediate runs synchronously until first actual suspension point, not just first await
- Main risk: overhang can block UI for hundreds of milliseconds on MainActor
- Useful for actor-isolated state updates from synchronous callbacks while preserving ordering
- Task groups gain addImmediateTask but can accidentally serialize parallel work
- Falls back to regular scheduling when requested actor doesn't match caller
Immediate tasks solve ordering problems when calling async code from synchronous actor contexts, but should only be used when the synchronous portion is guaranteed to be small and fast.
About This Article
Developers need to call async code from synchronous functions that are already running on the correct actor, like framework callbacks or @MainActor-isolated methods. The challenge is doing this without breaking execution ordering guarantees.
Antoine van der Lee describes Task.immediate, which uses explicit actor isolation syntax like Task.immediate { @MainActor in ... }. It starts execution right away on the caller's executor if the actor matches. If not, it falls back to normal scheduling.
Developers can update actor-isolated state before the caller continues. This means state changes like selectedPhotoID assignments happen synchronously without forcing the entire surrounding API to become async.