Многопоточные манипуляции с адресной книгой iPhone

Я уже некоторое время использую API AddressBook на iPhone. Но, проведя некоторый рефакторинг для повышения производительности приложения, я решил «повторно использовать» ABAddressBookRef, возвращаемый AddressBookCreate, потому что я заметил, что это значительно улучшает производительность. Однако теперь я случайным образом получаю ошибки EXEC_BAD_ACCESS, и я думаю, что причина кроется в этой «оговорке» в эталонной реализации iPhone: http://developer.apple.com/iphone/library/documentation/ContactData/Концептуальный/AddressBookProgrammingGuideforiPhone/300-BasicObjects/BasicObjects.html#//apple_ref/doc/uid/TP40007744-CH3-SW1

Важно: экземпляры ABAddressBookRef не могут использоваться несколькими потоками. Каждый поток должен создать свой собственный экземпляр, вызвав ABAddressBookCreate.

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

Может ли кто-нибудь подтвердить, действительно ли это проблема с потокобезопасностью (поэтому @synchronize должна работать) или какая-то другая проблема?

Ваше здоровье


person Marco    schedule 04.03.2010    source источник


Ответы (1)


Это не проблема безопасности потоков ... у вас нет способа решить ее с помощью блокировок. Комментарий проясняет это:

Важно: экземпляры ABAddressBookRef не могут использоваться несколькими потоками. Каждый поток должен создать свой собственный экземпляр, вызвав ABAddressBookCreate.

Что вы можете сделать, так это создать единственный экземпляр ABAddressBook и создать архитектуру производителя / потребителя, которая будет управлять доступом к объекту.

Оболочка будет иметь основной поток, который делает только одно: считывает запросы операций из очереди блокировки, а затем выполняет операции с адресной книгой. Все ваши потоки будут помещать свои операции в единую очередь, и оболочка выполнит эти действия; если в очереди ничего нет, оболочка будет блокироваться до тех пор, пока в очереди не будет ничего.

Это должно решить проблему запрета на использование ABAddressBookRef из нескольких потоков.

person Kiril    schedule 04.03.2010
comment
Привет, Лирик, да, я пришел к такому же выводу ... если честно, это похоже на очень плохой способ построить структуру AB ... разработчику остается создать (относительно) сложное многопоточное решение для решения общей проблемы это должно быть спроектировано, но что поделаешь ... Мне придется взяться за дело и сделать это трудным путем ... спасибо! - person Marco; 05.03.2010
comment
На самом деле, я построил другое решение, прежде чем прочитать ваш ответ, где я держал словарь ABRefs с именами потоков, думая (наивно), что iPhone перерабатывает потоки из пула потоков ... но хелас, без кубиков ... он создает новый нить каждый раз, когда вы отключаете одну ... итак, я наконец пришел к такому же выводу - person Marco; 05.03.2010
comment
@Lirik и @Marko, у меня такая же проблема. Я уже видел проблему с многопоточностью и с самого начала неплохо реализовал оболочку AB. Но у меня все равно огромная ошибка - иногда приложение вылетает, а иногда удаляет все контакты из АБ. Я трижды проверил, что все методы, использующие экземпляр AB, делают это из потока, которым управляет эта оболочка. - person Michael Kessler; 17.01.2011
comment
Есть ли шанс, что использование ABContactRef, полученного из AB, также должно выполняться из того же потока? В общем, я читаю контакты, сравниваю их с теми, что находятся в базе данных CoreData моего приложения и. Если есть изменения, я обновляю объекты Core Data, если есть дополнения, я добавляю их в локальную базу данных Core Data и т. Д. Любая помощь будет более чем оценена. Спасибо. - person Michael Kessler; 17.01.2011
comment
@Michael, к сожалению, я не очень знаком с программированием Apple ... Я ответил на этот вопрос только потому, что знаком с потоками. Это похоже на более глубокую проблему, и я предлагаю вам задать ее как отдельный вопрос. - person Kiril; 17.01.2011
comment
@Michael, согласно документации, вы также не можете (или не должны) передавать ссылки на записи по потокам. Вместо этого передайте идентификаторы (например, ABRecordGetRecordID). Если бы я догадался, я бы сказал, что это потому, что они ссылаются на ABAddressBookRef внутри. - person lilbyrdie; 24.06.2011