Home > Mobile >  Swift - async/await - Execute async method on background thread from MainActor Task
Swift - async/await - Execute async method on background thread from MainActor Task

Time:01-19

Here's my viewDidLoad method :

func viewDidLoad() {
    // Stuff here
    Task { @MainActor in 
        doSomeWorkOnMainThread1()
        doSomeWorkOnMainThread2()

        await doSomeBackgroundWork()

        doSomeWorkOnMainThread3()
        doSomeWorkOnMainThread4()
    }
}

And here's my method that should execute work on a background thread :

func doSomeBackgroundWork() async {
    // can add some code here
    // long image processing task
    assert(!Thread.isMainThread)
    // can add some code here
}

Is it possible to execute doSomeBackgroundWork on a background thread (without using GCD), and wait for it before going back to the main thread ?

CodePudding user response:

You are looking for Task.sleep. Note that it is in nanoseconds which is Really Weird, so I have written an extension to switch to seconds; to get it, you must use a Double, not an Int:

extension Task where Success == Never, Failure == Never {
    static func sleep(_ seconds:Double) async {
        await self.sleep(UInt64(seconds * 1_000_000_000))
    }
    static func sleepThrowing(_ seconds:Double) async throws {
        try await self.sleep(nanoseconds: UInt64(seconds * 1_000_000_000))
    }
}

The way to guarantee that a piece of work will be done on a background thread is to give that work to an Actor. That is what an Actor is for (in part).

So for example if an Actor has a method doSleep that calls Task.sleep, then if you instantiate that actor and call that method from your Task, it will sleep on a background thread.

CodePudding user response:

This solution is working, but it's not perfect I guess :

func doSomeBackgroundWork() async {
    await Task {
        // long image processing task
        assert(!Thread.isMainThread)
    }.result
}
  •  Tags:  
  • Related