2012-01-18 11 views
2

私は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(); 
} 

しかし、もちろん、これは主に目的に反し、呼び出し元のスレッドをブロックします。ブロックがスレッドの境界を越えない可能性はありますか?私はそうではないと思います。なぜなら、それは最初にそれらを持つという目的を大いに奪うからです。

答えて

4

は、ブロックがスタックと破壊の出口範囲に作成され、あなたがcopyを呼び出さない限り、それもretainが呼び出され、ヒープする移動しませんので、それ以外の場合は正しく保持されません[block copy]を呼び出すことを忘れないでください。

- (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]; 
} 
+0

ありがとうございました。私は実際に '[[syncBlock copy] autorelease]'を使用しました。次のように提案されています:http://stackoverflow.com/questions/5289306/iphone-exc-bad-access-when-using-blocks – aroth

関連する問題