我正在研究 Objective-C 中的 block ,试图提出一种可重用的机制,该机制将采用任意代码块和一个锁对象,然后在新线程上执行该代码块,并在提供锁。我们的想法是想出一种简单的方法来将所有同步开销/等待移出主线程,以便应用程序的 UI 始终具有响应能力。
我想出的代码非常简单,如下所示:
- (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:
之后崩溃,没有产生任何输出、错误消息、崩溃日志或任何其他有用的东西。我的方法有什么根本性的缺陷吗?如果没有,关于为什么这可能会崩溃有什么建议吗?
编辑:
有趣的是,如果我这样做,它就不会崩溃:
- (void) runAsyncBlock: (void (^)(void))block withLock:(id)lock {
void(^syncBlock)() = ^{
@synchronized(lock) {
block();
}
};
syncBlock();
}
但是这当然会阻塞调用线程,这在很大程度上违背了目的。 block 有可能不跨越线程边界吗?我认为不会,因为这很大程度上会违背最初拥有它们的目的。
最佳答案
记住调用[block copy]
,否则它不会正确保留,因为 block 是在堆栈上创建的,并在退出范围时销毁,除非您调用copy
,否则它不会移动甚至调用 retain
来堆。
- (void) runAsyncBlock: (void (^)(void))block withLock:(id)lock {
block = [[block copy] autorelease];
void(^syncBlock)() = ^{
@synchronized(lock) {
block();
}
};
syncBlock = [[syncBlock copy] autorelease];
[self performSelectorInBackground:@selector(executeBlock:) withObject:syncBlock];
}
关于objective-c - 同步块(synchronized block)内的 block ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8906026/