Nox
Nox

Reputation: 1583

Multithreading for loops in Swift 4

I need a bit of help on proper for loop multithreading for swift 4. Should I use a normal dispatch queue or should I use concurrent threading? Or am I thinking about this wrong? The specific instance I am looking at here is: say we want to do something to a list of objects, such as retrieve a user picture from a database for all users that are missing one in a local database on the device.

let utilityQueue = DispatchQueue(label: "com.company.utility", qos: .utility)
for i in 1 ... 10000 {
    utilityQueue.async {
        getMissingImage(user[i])
    }
}

The above seems to work for me, but I found another option in my reading, but using concurrency such as below

let concurrentQueue = DispatchQueue(label: "com.company.concurrent", attribute: .concurrent)
for i in 1 ... 10000 {
    concurrentQueue.async {
        getMissingImage(user[i])
    }
}

Which is correct or is there a better way to handle this that I am missing?

Upvotes: 1

Views: 2346

Answers (1)

Rob
Rob

Reputation: 437432

The attempt to start an unconstrained number of concurrent tasks, is dangerous, because GCD has a very limited number of worker threads and if you exhaust them, you can adversely impact other operations within the app.

So consider your example:

let concurrentQueue = DispatchQueue(label: "com.company.concurrent", attributes: .concurrent)
for i in 0 ..< 10_000 {
    concurrentQueue.async {
        self.getMissingImage(self.user[i])
    }
}

You might use OperationQueue which lets you easily constrain the degree of concurrency, in this example not more than 4 at a time:

let queue = OperationQueue()
queue.name = "com.company.concurrent"
queue.qualityOfService = .userInitiated
queue.maxConcurrentOperationCount = 4

for i in 0 ..< 10_000 {
    queue.addOperation {
        self.getMissingImage(self.user[i])
    }
}

You can accomplish something similar with GCD semaphores, but it’s a little more fragile and I’d suggest the above.

Note, this assumes that getMissingImage runs synchronously (i.e. will not return until the task is completely done). If not, you’ll have to pursue other patterns.

Upvotes: 1

Related Questions