Аналогично @ 仲耀晖 у меня был неправильный тип приложения, настроенный для dll. Я предполагаю, что тип проекта изменился из-за некорректного копирования, как предположил @Daniel Struhl.
Как проверить: Щелкните правой кнопкой мыши по проекту -> properties
-> Configuration Properties
-> General
-> Project Defaults
-> Configuration Type
.
Проверьте, содержит ли это поле правильный тип, например «Dynamic Library (.dll)», если проект является dll.
Если возможно, что к любым данным (включая классы) получат доступ от двух потоков одновременно, необходимо предпринять шаги для хранения, они синхронизировались.
, К счастью, Objective C делает смехотворно легким сделать это использование синхронизируемого ключевого слова. Это ключевые слова берет в качестве аргумента любой объект Objective C. Любые другие потоки, которые указывают тот же объект в синхронизируемом разделе, остановятся до первых концов.
-(void) doSomethingWith:(NSArray*)someArray
{
// the synchronized keyword prevents two threads ever using the same variable
@synchronized(someArray)
{
// modify array
}
}
, Если необходимо защитить больше, чем всего одна переменная, необходимо рассмотреть использование семафора, который представляет доступ к тому набору данных.
// Get the semaphore.
id groupSemaphore = [Group semaphore];
@synchronized(groupSemaphore)
{
// Critical group code.
}
Существует несколько способов сделать это. Самое простое в Вашем случае должно было бы, вероятно, использовать @synchronized директиву. Это позволит Вам создавать взаимное исключение на лету с помощью произвольного объекта в качестве блокировки.
@synchronized(sStaticData) {
// Do something with sStaticData
}
Иначе должен был бы использовать класс NSLock. Создайте блокировку, которую Вы хотите использовать, и затем у Вас будет немного больше гибкости когда дело доходит до получения взаимного исключения (относительно блокирования, если блокировка будет недоступна, и т.д.).
NSLock *lock = [[NSLock alloc] init];
// ... later ...
[lock lock];
// Do something with shared data
[lock unlock];
// Much later
[lock release], lock = nil;
, Если Вы решаете проявить любой из этих подходов, будет необходимо получить блокировку и для чтений и для записей, так как Вы используете NSMutableArray/Set/whatever в качестве хранилища данных. Поскольку Вы видели, что NSFastEnumeration запрещает мутацию перечисляемого объекта.
, Но я думаю, что другой проблемой здесь является выбор структур данных в многопоточной среде. Действительно ли строго необходимо получить доступ к Вашим словарям/массивам от нескольких потоков? Или фоновые потоки могли объединить данные, они получают и затем передают их основному потоку, который был бы единственным потоком, позволенным получить доступ к данным?
In response to the sStaticData and NSLock answer (comments are limited to 600 chars), don't you need to be very careful about creating the sStaticData and the NSLock objects in a thread safe way (to avoid the very unlikely scenario of multiple locks being created by different threads)?
I think there are two workarounds:
1) You can mandate those objects get created at the start of day in the single root thread.
2) Define a static object that is automatically created at the start of day to use as the lock, e.g. a static NSString can be created inline:
static NSString *sMyLock1 = @"Lock1";
Then I think you can safely use
@synchronized(sMyLock1)
{
// Stuff
}
Otherwise I think you'll always end up in a 'chicken and egg' situation with creating your locks in a thread safe way?
Of course, you are very unlikely to hit any of these problems as most iPhone apps run in a single thread.
I don't know about the [Group semaphore] suggestion earlier, that might also be a solution.