Недостаточно места для копирования содержимого массива - PullRequest
0 голосов
/ 28 сентября 2019

Я создаю некоторый код для запроса нескольких данных из базы данных, чтобы иметь расписание в моем интерфейсе, вкл.несколько запросов к БД.

Проблема в том, что с одним конкретным запросом где.Я использую swiftKuery и DispatchGroups, я получаю иногда, но не всегда сообщение об ошибке в моем 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 ???но это единственное, что я думаю, как идея ....

1 Ответ

0 голосов
/ 28 сентября 2019

Скорее всего, это вызвано некоторыми условиями гонки из-за того, что вы модифицируете массив из нескольких потоков.И если два потока попытаются изменить массив одновременно, вы столкнетесь с проблемами.

Убедитесь, что вы сериализовали доступ к массиву, это должно решить проблему.Для этого вы можете использовать семафор:

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


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()

Семафор здесь действует как мьютекс, позволяя не более одного потока работать с массивом.Также я хотел бы подчеркнуть тот факт, что блокировка должна удерживаться как можно меньше времени, чтобы другим потокам не приходилось слишком долго ждать.

...