There's a subtle conflict in terminology here that I think is the root of the misunderstanding.
It's common in UI programming to talk about "background threads" to mean, essentially, any thread that's not the UI-processing thread. Using that definition, every DispatchQueue is "background" (unless it either is or targets DispatchQueue.main): if you enqueue something to run asynchronously on the queue, it will be processed on a non-UI thread.
It is also common in threading libraries (and similar abstractions like DispatchQueues and Swift tasks) to allow threads/queues/tasks to have an execution priority. The idea is that operations that need to execute more urgently are given higher execution priority, allowing them to not be interrupted by less urgent operations. The UI thread in UI programming is generally given a very high priority so that other work doesn't prevent the UI from promptly redrawing itself and responding to user interactions. In POSIX, threads have a numeric execution priority, the exact interpretation of which is pretty system-specific; here's some docs about Linux. In Swift, we follow the lead of DispatchQueue QoS by intentionally narrowing that down to a small number of named priorities.
Now, one of those named priorities happens to be called background; it's meant for low-priority work like periodically cleaning up various data structures. But this "background priority" is not the same thing as being a "background thread", and even in Dispatch, you should generally not be using a background queue just because you want work to not be done on the UI thread. Most work that's initiated by a UI event should be userInitiated so that it doesn't get excessively delayed.
So I think you're thinking about passing priority: .background to Task.init as if it were an instruction to run the task on a background thread. Hopefully you understand now that it isn't. Of course, that just raises the question of how you're supposed to tell Task.init where to run. This is a really important difference between Swift concurrency and the traditional way you do programming around DispatchQueues.
In typical queue-oriented concurrency, a lot of data is protected from data races by only accessing it on a specific serial queue. In a world like that, in order for Swift to have any hope of proving that a function doesn't create data races, the compiler needs to understand something about where that function is running. That's not really compatible with just running functions on whatever queue you happen to pass at the same time to dispatch_async. So in Swift concurrency, the fact that a function is supposed to run on a specific queue (we say "actor", but an actor is basically just a serial queue + some associated data that protected by that queue) is basically part of the function's static type, and a whole lot of the concurrency language mechanics are designed around preserving that and making sure that functions run in the right place.
That's why, if you want a task to start running on a background thread, you don't just pass something special to Task.init. You have to make sure the function itself "knows" that it's not supposed to run on the main actor. That's why Jon Shier and I were talking above about how to declare that a closure is non-isolated: if the current function is @MainActor, then a closure passed to Task.init will normally also be inferred to be @MainActor. You can override that by writing Task { @concurrent in ... }: the @concurrent attribute on the closure changes its isolation to say that it no longer needs to be run on the main actor, which ultimately means it'll run on a "background thread" in the sense you originally meant it.