我正在构建一些代码来请求数据库中的多个信息,以便在前端有一个时间表,包括多个数据库请求。
问题是在一个特定的请求中。在使用swiftKuery和DispatchGroups时,我会收到ooccasionly,但并不总是在XCode中收到错误消息。这不能通过不同的请求重建,但有时会发生。
这是我的一段代码。

var profWorkDaysBreak = [time_workbreaks]()
let groupServiceWorkDayBreaks = DispatchGroup()

...

  ///WorkdaysBreakENTER AsyncCall
        //UnreliableCode ?
        profWorkDays.forEach {workDay in
            groupServiceWorkDayBreaks.enter()
            time_workbreaks.getAll(weekDayId: workDay.id) { results, error in
                if let error = error {
                    print(error)
                }
                if let results = results {
                    profWorkDaysBreak.append(contentsOf: results) // The error happens here !
                }
                groupServiceWorkDayBreaks.leave()
            }
        }

...

groupServiceWorkDayBreaks.wait()


结果和profWorkDaysBreak变量是相同的,只是有时我收到消息:
致命错误:分配给复制数组内容的空间不足
这导致了死刑的终止。
我想,循环有时可能会在DispatchGroup中完成先前的执行??? 但这是我唯一的想法。。。。

最佳答案

这很可能是由于某些争用条件造成的,因为您可以从多个线程修改数组。如果两个线程同时尝试改变数组,就会出现问题。
确保序列化对数组的访问,这将解决问题。您可以使用信号量:

var profWorkDaysBreak = [time_workbreaks]()
let groupServiceWorkDayBreaks = DispatchGroup()
let semaphore = DispatchSemaphore(value: 0)
...


profWorkDays.forEach { workDay in
    groupServiceWorkDayBreaks.enter()
    time_workbreaks.getAll(weekDayId: workDay.id) { results, error in
        if let error = error {
            print(error)
        }
        if let results = results {
            // acquire the lock, perform the non-thread safe operation, release the lock
            semaphore.wait()
            profWorkDaysBreak.append(contentsOf: results) // The error happens here !
            semaphore.signal()
        }
        groupServiceWorkDayBreaks.leave()
    }
}

...

groupServiceWorkDayBreaks.wait()

这里的信号量就像一个互斥锁,最多允许一个线程对数组进行操作。另外,我想强调一个事实,即锁应该被保持尽可能短的时间,这样其他线程就不必等待太久。

10-08 10:52