3

iOSのGCDを介してメインキューにコードをディスパッチしようとしていますが、最も単純なテストでさえ常に失敗します。結局、それはこれに要約されます:

static const int TICK_INTERVAL = 1;

#pragma UIApplicationDelegate implementation

- (void) doTick
{
    if (![NSThread isMainThread])
    {
        NSLog(@"Trying to dispatch . . .");
        dispatch_sync(dispatch_get_main_queue(), ^{
            NSLog(@"test . . .");
        });
    }
}

- (void) startUpdate
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        timer_ = [NSTimer
                  scheduledTimerWithTimeInterval:TICK_INTERVAL
                  target:self
                  selector:@selector(backgroundUpdate)
                  userInfo:nil
                  repeats:NO
                  ];

        [[NSRunLoop currentRunLoop]
         addTimer:timer_
         forMode:NSRunLoopCommonModes
         ];

        [[NSRunLoop currentRunLoop] run];
    });

    UIBackgroundTaskIdentifier back =
    [[UIApplication sharedApplication]
     beginBackgroundTaskWithExpirationHandler:^{
         [self doTick];
         [[UIApplication sharedApplication]
          endBackgroundTask:back
          ];
     }];
}

-(void)backgroundUpdate
{
    [self doTick];

    UIBackgroundTaskIdentifier back =
    [[UIApplication sharedApplication]
     beginBackgroundTaskWithExpirationHandler:^{
         [self doTick];
         [[UIApplication sharedApplication]
          endBackgroundTask:back
          ];
     }];

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            timer_ = [NSTimer
                     scheduledTimerWithTimeInterval:TICK_INTERVAL
                     target:self
                     selector:@selector(backgroundUpdate)
                     userInfo:nil
                     repeats:NO
                     ];

            [[NSRunLoop currentRunLoop]
             addTimer:timer_
             forMode:NSRunLoopCommonModes
             ];

            [[NSRunLoop currentRunLoop] run];
        });
}

- (id) init
{   
    self = [super init];
    [self startUpdate];
    return self;
}

それは私のAppDelegateです。上記のテストテキストをログに記録するためにメインスレッドでNSLogが実行されることを期待しますが、何も起こりません。dispatch_syncコードは永久に待機し、ブロック内に配置したブレークポイントに到達することはありません。

コードがメインスレッドで実行されないようにしました。でテストする前に、アプリでdispatch_sync実験しdispatch_asyncました。もちろん、結果は基本的に同じです。何も起こりません(ブロックなし)。

興味深いことに、メインキューでは機能しないようで、他のキュー(現在のキュー、グローバルキュー)は問題なく機能しているように見えます。

意味がある場合は、アプリでPhonegap(Cordova)を使用しています。

何かアイデアはありますか?

どうもありがとう!

4

1 に答える 1

4

dispatch_syncキューで実行中のタスクから同じキューに移動しないでください。これは、メイン キューのような任意のシリアル キューでデッドロックが発生することが保証されており、同時キューではお勧めできません。詳細については、 Apple の同時実行プログラミング ガイドを参照してください。アプリケーション デリゲートの init メソッドはメイン スレッドで実行されるdispatch_syncため、メイン キューに対してはデッドロックが発生します。

dispatch_asyncメイン スレッドで通常の NSRunLoop を実行している限り、メイン キューへの接続は機能します。もちろん、NSLog(@"test . . .")アプリケーション デリゲートの init メソッドの完了よりも大幅に遅れて実行される可能性があります。

于 2012-06-10T01:25:53.980 に答える