闪电狮
闪电狮

Reputation: 556

How to use Dispatch?

The compiler said,

Cannot pass function of type '() async -> Void' to parameter expecting synchronous function type

enter image description here

This is the problem code:

DispatchQueue.global().async {    
    await CreateFolder()
    
    do {
        let FilePath = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
        let FileName = UUID().uuidString
        try! Image.pngData()!.write(to: FilePath.appendingPathComponent("Images").appendingPathComponent("\(FileName).png"))
    } catch {
        Prompt(error.localizedDescription)
    }
}

Upvotes: 0

Views: 185

Answers (3)

Rob
Rob

Reputation: 437392

We can tell that CreateFolder is not an async method, and as a result, you should not await it when calling it from within the GCD dispatch.

But the deeper problem is that you should avoid GCD queues when using async-await. You want to use the Swift concurrency cooperative thread pool. To do that, you would use Task.

But you do not want Task { ... } (or Task.init { ... }). If you want this behavior of running it in the background (like your global queue example), you would create a detached task:

Task.detached {
    CreateFolder() // you may now need the `await`, unless this function is marked as `nonisolated`
    
    ...
}

We use Task { ... } when we want to launch a task on the current actor, but one that honors the Swift concurrency contract to never prevent forward progress. We use Task.detached { ... } when the code being run is slow and synchronous and does not honor the Swift concurrency contract.

Upvotes: 2

Ali Murad
Ali Murad

Reputation: 132

Async methods call in a function that does not support concurrency. You can use Task.init

Task.init {
            do {
                   _ = try await CreateFolder()
                   let FilePath = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
                           let FileName = UUID().uuidString
                           try! Image.pngData()!.write(to: FilePath.appendingPathComponent("Images").appendingPathComponent("\(FileName).png"))
               } catch {
                   Prompt(error.localizedDescription)
               }
           }

Upvotes: 1

闪电狮
闪电狮

Reputation: 556

Remove await from DispatchQueue closure.

Fixed:

    DispatchQueue.global().async {
   
    
    CreateFolder()
    
    do {
        let FilePath = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
        let FileName = UUID().uuidString
        try! Image.pngData()!.write(to: FilePath.appendingPathComponent("Images").appendingPathComponent("\(FileName).png"))
    } catch {
        Prompt(error.localizedDescription)
    }
    }

Upvotes: 0

Related Questions