Я играю с блоками в Objective-C, пытаюсь придумать механизм многократного использования, который возьмет произвольный блок кода и объект блокировки, а затем выполнит блок кода в новом потоке, синхронизированном на при условии блокировки. Идея состоит в том, чтобы придумать простой способ переместить все накладные расходы на синхронизацию / ожидание основного потока, чтобы пользовательский интерфейс приложения всегда был отзывчивым.
Код, который я придумал, довольно прост, он выглядит так:
- (void) executeBlock: (void (^)(void))block {
block();
}
- (void) runAsyncBlock: (void (^)(void))block withLock:(id)lock {
void(^syncBlock)() = ^{
@synchronized(lock) {
block();
}
};
[self performSelectorInBackground:@selector(executeBlock:) withObject:syncBlock];
}
Так, например, у вас могут быть такие методы, которые выглядят так:
- (void) addObjectToSharedArray:(id) theObj {
@synchronized(array) {
[array addObject: theObj];
}
}
- (void) removeObjectFromSharedArray:(id) theObj {
@synchronized(array) {
[array removeObject: theObj];
}
}
Что отлично работает, но блокирует вызывающий поток во время ожидания блокировки. Они могут быть переписаны как:
- (void) addObjectToSharedArray:(id) theObj {
[self runAsyncBlock:^{
[array addObject: theObj];
} withLock: array];
}
- (void) removeObjectFromSharedArray:(id) theObj {
[self runAsyncBlock: ^{
[array removeObject: theObj];
} withLock:array];
}
Который должен всегда возвращаться немедленно, поскольку только фоновые потоки будут конкурировать за блокировку.
Проблема в том, что этот код падает после executeBlock:
без вывода какого-либо вывода, сообщения об ошибке, журнала сбоя или каких-либо других полезных вещей. Есть ли в моем подходе что-то принципиальное? Если нет, какие-либо предложения относительно того, почему это может быть сбой?
Edit:
Интересно, что он работает без сбоев, если я просто сделаю:
- (void) runAsyncBlock: (void (^)(void))block withLock:(id)lock {
void(^syncBlock)() = ^{
@synchronized(lock) {
block();
}
};
syncBlock();
}
Но, конечно, это заблокирует вызывающий поток, который в значительной степени побеждает цель. Возможно ли, что блоки не пересекают границы потоков? Я думаю, что нет, так как это в значительной степени победило бы цель иметь их в первую очередь.