Cheok Yan Cheng
Cheok Yan Cheng

Reputation: 42700

Is using Task.detached a best practice and correct approach, to make sure the Task is executed in non-main thread?

Currently, I have the following code

class ShopViewController: UIViewController {
    
    @IBAction func buy(_ sender: Any) {
        Task {
            // Will run in main thread, because ShopViewController is
            // marked as @MainActor
            let success = await Store.INSTANCE.purchase(selectedShop)
        }
    }

I want the Task executes in non-main thread, I refactor the code to the following

class ShopViewController: UIViewController {
    
    @IBAction func buy(_ sender: Any) {
        Task.detached { [weak self] in
            // Will run in non main thread.

            guard let self = self else { return }

            let success = await Store.INSTANCE.purchase(self.selectedShop)
        }
    }

Now, the Task runs in non-main thread.

But, I was wondering, is using Task.detached a best practice and correct approach, to make sure the Task is executed in non-main thread?

Upvotes: 2

Views: 1183

Answers (1)

Rob
Rob

Reputation: 437552

There are a few considerations:

  • Which actor should this Task use?

    Using the main actor with Task { … } is fine. As soon as it hits the await keyword, it will suspend execution on the main actor, free it to go do other stuff, and await the results from purchase. In fact, in practice, you are probably doing something with the success result (e.g. updating the UI), so you probably want to use Task { … } to keep it on the current actor.

  • Which actor should purchase use?

    If Store.INSTANCE.purchase requires a particular actor, it would define which actor it wants to use, not the caller. It might be an actor type. It might be decorated with @MainActor. This is dictated by how Store.INSTANCE and purchase are defined. The actor used by buy(_:) is largely immaterial.

  • Does it matter which actor purchase uses?

    You say that purchase is primarily performing network i/o. In that case, it doesn’t matter if it is on the main actor or not. If it was doing something slow and synchronous (e.g., parsing some exceptionally large responses, image processing, etc.), when maybe you would want to explicitly push those tasks off of the current actor, but otherwise it doesn’t matter.

Bottom line, the use of Task.detached is technically permissible, but generally would not be used in this case.

Upvotes: 2

Related Questions