同步块内的块?

时间:2012-01-18 06:23:37

标签: objective-c closures objective-c-blocks

我正在使用Objective-C中的块,试图找到一个可重用的机制,它将获取任意代码块和一个锁对象,然后在新线程上执行代码块,同步提供锁定。我们的想法是提出一种简单的方法来移动主线程的所有同步开销/等待,以便应用程序的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();
}

但当然这会阻止调用线程,这在很大程度上违背了目的。块是否可能不跨越线程边界?我不这么认为,因为那样会在很大程度上打败首先拥有它们的目的。

1 个答案:

答案 0 :(得分:4)

记得调用[block copy]否则它没有被正确保留,因为块在堆栈上创建并在退出范围时被销毁,除非你调用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];
}