Why would using Swift DispatchGroup load CPU to 1000%?

I have some code that calls an external library asynchronously to read EXIF keywords from image files :

Code Block
func readKeywords()
{
keywordsForSelectedItems.removeAll()
let group: DispatchGroup = .init()
let queue: DispatchQueue = .init(label: "com.keywords")
collectionView.selectionIndexPaths.forEach
{
indexPath in
let item = self.collectionView.item(at: indexPath) as! CollectionViewItem
let url = item.url!
group.enter()
queue.async(group: group)
{
do
{
try ExifReader.keywords(for: url)
{
keywords in
if let keywords = keywords,
keywords.count > 0
{
self.keywordsForSelectedItems.append(keywords)
}
group.leave()
}
}
catch
{
print(error.localizedDescription)
}
}
}
group.notify(queue: .main)
{
let firstValue: [String]? = self.keywordsForSelectedItems.first
{
keywords in
keywords.count > 0
}
if firstValue != nil
{
let keywords = self.keywordsForSelectedItems.reduce(Set(firstValue!))
{
result, item in
result.union(item)
}
self.tokenView.objectValue = keywords.sorted()
}
}
}

Before I added this code, everything worked fine and images were displayed perfectly in a CollectionView.

But, since adding this code, as soon as this code has been called, the CPU fan starts to run, anywhere up to 1000% at times and it can block other asynchronous processes that normally load images in the background.

Anyone got any ideas?

Replies

I cannot say anything sure as you are not showing enough code to reproduce the issue.

But at least you need to fix one thing with this line:
Code Block
self.keywordsForSelectedItems.append(keywords)

I guess keywordsForSelectedItems is a Swift Array, which is not thread-safe.

You should not access a Swift Array from multiple threads.

You may need to prepare a serial queue for the Array, and access it only within the queue.