How do I perform a synchronous operation inside an async function without blocking the main thread?

How can I ensure a heavy synchronous operation inside an async function does not run on the @MainActor? I don't want it to block the main thread no matter where it's called from, but I still would like to inherit actor context and priority for the actual async task inside it.

// This function can be called from anywhere.
func downloadThumbnail(url: URL) -> async {
	// I want this to inherit the actor context and priority.
	let data = await download(url)

	// How can I ensure this part does NOT run on `@MainActor`?
	// Heavy operation.
	return Image(data).resized(width: 400, height: 400)
}

My first thought would be:

func downloadThumbnail(url: URL) -> async {
	let data = await download(url)
	return await Task { Image(data).resized(width: 400, height: 400) }.value
}

(I haven't actually tested if this works)

Is there a better way or am I maybe thinking about this all wrong?

You should use Task.detach so as not to inherit the main executor/actor. You can also use withContinuation to kick things off in the background manually.

1 Like