6

Grand Central Dispatch は優れており、コードの量を削減しますが、バックグラウンド スレッドで何かを実行できないのはなぜですか?
私が何を意味するかを示すサンプルアプリケーションを作成しました(コメントされた作業はありません):

- (IBAction)performSel {
    [self performSelectorInBackground:@selector(doStuff) withObject:nil];
    [NSThread sleepForTimeInterval:3];
    [[self.view.subviews lastObject] removeFromSuperview];
}

- (IBAction)gcd {
    dispatch_async(dispatch_queue_create("myGCDqueue", NULL), ^(void) {
    //dispatch_sync(dispatch_queue_create("myGCDqueue", NULL), ^(void) {
    //dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
    //dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
    //dispatch_async(dispatch_get_main_queue(), ^(void) {
    //dispatch_sync(dispatch_get_main_queue(), ^(void) {
        [self doStuff]; // only for readability, will move the code on success
    });
    [NSThread sleepForTimeInterval:3];
    [[self.view.subviews lastObject] removeFromSuperview];
}

- (void)doStuff {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];

    UIView *abortingView = [[UIView alloc]initWithFrame: self.view.bounds];
    abortingView.backgroundColor = [UIColor whiteColor];
    abortingView.alpha = 0.7;
    [self.view insertSubview:abortingView atIndex:10];
    [abortingView release];

    [pool drain];
}

これ[NSThread sleepForTimeInterval:3];は、デフォルトの UI 機能をシミュレートするためのものです。たとえば、あるナビゲーション ビューから別のナビゲーション ビューに切り替えている場合などです。
新しいビュー ベースのアプリケーションにコードをコピーし、2 つのボタンを作成して接続するだけです。

4

1 に答える 1

24

UIKitクラスは、アプリケーションのメインスレッドからのみ使用する必要があります。(iOS4から、グラフィックスコンテキストへの描画はスレッドセーフです。)バックグラウンドスレッドでUIKitのものを使用することはできません。

したがって、この状況では、dispatch_async(dispatch_get_main_queue()、block)のみを使用できます。

dispatch_async(dispatch_get_main_queue(), ^(void) {

メインスレッドの実行ループ内のメインスレッドでブロックを呼び出します。

dispatch_async(dispatch_queue_create("myGCDqueue", NULL), ^(void) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {

バックグラウンドスレッドでブロックを呼び出します。ブロック内でUIKitを使用したいので使用できません。また、 dispatch_async(dispatch_queue_create(、メモリリークが発生する可能性があるため、dispatch_queue_createによって作成されたシリアルキューを解放する必要があることに注意してください。

dispatch_sync(dispatch_queue_create("myGCDqueue", NULL), ^(void) {
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {

dispatch_syncは、ブロックが完了するまで待機します。

dispatch_sync(dispatch_get_main_queue(), ^(void) {

デッドロックが発生します。

于 2011-04-07T00:53:04.540 に答える